Skip to content

Instantly share code, notes, and snippets.

@takimo
Last active December 24, 2015 15:29
Show Gist options
  • Save takimo/6821173 to your computer and use it in GitHub Desktop.
Save takimo/6821173 to your computer and use it in GitHub Desktop.
HubotでAndroidのクラッシュレポート(GooglePlay)をIRCのチャンネルに通知するスクリプト
/*
* @name get_error_report_by_casper.js
* @description GooglePlayStoreからクラッシュレポートを取得するcasper用のスクリプト
* @example
* casperjs ./scripts/get_error_report_by_casper.js --dev_acc="casper_cli_bug_prefix-04467794333284148" --app=example.com --email=test@example.com --password=hogefuga
*/
var casper = require('casper').create({
pageSettings: {
javascriptEnabled: true
}
});
var validateAndGetCli = function(name){
if(!casper.cli.has(name)) throw new Error("undefined --" + name);
return casper.cli.get(name);
};
// [note]
// casper.cli.getで取得できる数字の桁数の上限に引っかかるためわざと文字列として判断されるように文字を入れている"
var DEV_ACC = validateAndGetCli("dev_acc").replace("casper_cli_bug_prefix-","");
var APP = validateAndGetCli("app");
var EMAIL = validateAndGetCli("email");
var PASSWORD = validateAndGetCli("password");
casper.start("https://play.google.com/apps/publish/?dev_acc=" + DEV_ACC + "#ErrorClusterListPlace:p=" + APP, function(){
this.evaluate(function(email, password) {
document.querySelector('#Email').value = email;
document.querySelector('#Passwd').value = password;
document.querySelector('#signIn').click();
}, EMAIL, PASSWORD);
});
casper.then(function(){
this.evaluate(function(){
var form = document.querySelector('#frm');
form.later.value = '1';
form.submit();
});
});
casper.thenOpen("https://play.google.com/apps/publish/?dev_acc=" + DEV_ACC + "#ErrorClusterListPlace:p=" + APP, function(){
this.wait(5000, function(){
this.evaluate(function(){
var click = function(el){
var ev = document.createEvent("MouseEvent");
ev.initMouseEvent(
"click",
true /* bubble */,
true /* cancelable */,
window,
null,
0, 0, 0, 0, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}
click(document.querySelector('span[data-type=reportsThisWeek]'));
});
this.capture('capture.png');
});
});
casper.then(function(){
this.wait(5000, function(){
var result = this.evaluate(function(){
var trList = document.querySelectorAll('tr:not([__gwt_header_row])');
var _errors = [];
var catchs = [];
Array.prototype.slice.apply(trList).forEach(function(tr){
try{
var errorDescription = tr.querySelector('[data-type=errorDescription]') ? tr.querySelector('[data-type=errorDescription]').innerText : "";
var errorLocation = tr.querySelector('[data-type=errorLocation]') ? tr.querySelector('[data-type=errorLocation]').innerText : "";
var newLabel = tr.querySelector('[data-type=newLabel]') ? !!(tr.querySelector('[data-type=newLabel]').innerText == "初回") : false;
var reportsThisWeek = tr.querySelector('[data-type=reportsThisWeek]') ? tr.querySelector('[data-type=reportsThisWeek]').innerText : "";
var reportsTotal = tr.querySelector('[data-type=reportsTotal]') ? tr.querySelector('[data-type=reportsTotal]').innerText : "";
var lastReportingDate = tr.querySelector('td:nth-of-type(5)') ? tr.querySelector('td:nth-of-type(5)').innerText : "";
_errors.push({
'errorDescription': errorDescription,
'errorLocation': errorLocation,
'newLabel': newLabel,
'reportsThisWeek': reportsThisWeek,
'reportsTotal': reportsTotal,
'lastReportingDate': lastReportingDate
});
}catch(e){
catchs.push(e);
}
});
return {
errors: _errors,
catchs: catchs
};
});
//this.echo(JSON.stringify(errors, null, " "));
//this.echo(JSON.stringify(result.errors, null, " "));
this.echo(JSON.stringify(result.errors));
//this.echo(JSON.stringify(result.catchs));
//this.echo(result.errors.length);
//this.echo(result.catchs.length);
});
});
casper.run();
module.exports = function(robot){}
/*
* @name notify android report
* @description GooglePlayStore上のアプリのクラッシュレポートを特定のチャンネルに通知します
* @dependency
* get_error_report_by_casper.jsをscripts以下に配置する
* @todo
* レスポンスがかえってこなくてとれない時がある
* 環境変数で以下を定義する必要があります
* export NOTIFY_ANDROID_ERROR_CHANNEL = "#report-channel"
* export NOTIFY_ANDROID_ERROR_DEFAULT_DEV_ACC="XXXXXXXXXXXXXXX"
* export NOTIFY_ANDROID_ERROR_APP="com.example"
* export NOTIFY_ANDROID_ERROR_EMAIL="test@example.com"
* export NOTIFY_ANDROID_ERROR_PASSWORD="hogefuga"
*/
// ::require
var _ = require('underscore');
var cronJob = require('cron').CronJob;
var exec = require('child_process').exec;
var color = require('irc-colors');
// ::validation
var validateEnv = function(name){
if(!process.env[name]) throw new Error('not defined ' + name);
};
validateEnv("NOTIFY_ANDROID_ERROR_CHANNEL");
validateEnv("NOTIFY_ANDROID_ERROR_DEFAULT_DEV_ACC");
validateEnv("NOTIFY_ANDROID_ERROR_APP");
// ::constant
var REPORT_URL = "https://play.google.com/apps/publish/?dev_acc=" + process.env.NOTIFY_ANDROID_ERROR_DEFAULT_DEV_ACC + "#ErrorClusterListPlace:p=" + process.env.NOTIFY_ANDROID_ERROR_APP;
// ::script
var messageIRC = function(robot, errors){
var irc = robot.userForId(process.env.NOTIFY_ANDROID_ERROR_CHANNEL);
irc.room = '';
irc.type = 'groupchat';
robot.send(irc, "Android Error Report " + REPORT_URL);
_.each(errors, function(error){
var newLabel = (error.newLabel) ? color.red("[初回]") : ""
robot.send(irc, newLabel + error.errorDescription);
robot.notice(irc, error.errorLocation);
robot.notice(irc, "week: " + error.reportsThisWeek +" / total: " + error.reportsTotal);
});
};
var getErrorReport = function(callback){
// [note]
// casper.cli.getで取得できる数字の桁数の上限に引っかかるためわざと文字列として判断されるように文字を入れている
var CASPER_CLI_BUG_PREFIX = "casper_cli_bug_prefix-";
var cmd = [
"casperjs",
"./scripts/get_error_report_by_casper.js",
"--dev_acc=" + CASPER_CLI_BUG_PREFIX + process.env.NOTIFY_ANDROID_ERROR_DEFAULT_DEV_ACC,
"--app=" + process.env.NOTIFY_ANDROID_ERROR_APP,
"--email=" + process.env.NOTIFY_ANDROID_ERROR_EMAIL,
"--password=" + process.env.NOTIFY_ANDROID_ERROR_PASSWORD,
].join(" ");
exec(cmd, {timeout: 30000}, function(error, stdout, stderr){
try{
var errors = JSON.parse(stdout);
callback(errors);
}catch(e){
console.log(e.toString());
}
});
}
var startCronJob = function(robot){
var setting = {
cronTime: '00 00 10-19 * * *',
onTick: function(){
getErrorReport(function(errors){
messageIRC(robot, errors.slice(0,5));
});
},
start: false,
timeZone: 'Asia/Tokyo'
};
var job = new cronJob(setting);
job.start();
};
// ::exports
module.exports = function(robot){
startCronJob(robot);
robot.respond(/report android error/, function(msg){
var irc = robot.userForId(process.env.NOTIFY_ANDROID_ERROR_CHANNEL);
irc.room = '';
irc.type = 'groupchat';
robot.send(irc, "ok! please wait...");
getErrorReport(function(errors){
messageIRC(robot, errors.slice(0,5));
});
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment