Last active
December 24, 2015 15:29
-
-
Save takimo/6821173 to your computer and use it in GitHub Desktop.
HubotでAndroidのクラッシュレポート(GooglePlay)をIRCのチャンネルに通知するスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* @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){} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* @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