Skip to content

Instantly share code, notes, and snippets.

@seya128
Created October 5, 2016 08:52
Show Gist options
  • Save seya128/63ddd9569c42af4f716a8a6567804de3 to your computer and use it in GitHub Desktop.
Save seya128/63ddd9569c42af4f716a8a6567804de3 to your computer and use it in GitHub Desktop.
アプリのレビューをメールしてくれるやつ GAS
var MAIL_TO = "mail1@domain,mail2@domain";
var MAIL_TITLE = "アプリレビュー";
//
// 前回取得日から昨日のアプリレビューをメール送信する
//
function sendMailYesterdayReview() {
//スプレッドシートに記載のアプリIDのレビューを取得、整形
var text = "";
text += jobSheet("AppStore", "Dorasu AppStore");
text += jobSheet("GooglePlay", "Dorasu GooglePlay");
text += jobSheet("AppStore", "etc AppStore");
text += jobSheet("GooglePlay", "etc GooglePlay");
//取得したレビューをメール送信
if (text != "") {
MailApp.sendEmail(MAIL_TO, MAIL_TITLE, text);
Logger.log("メール送信 to:"+MAIL_TO+" title:"+MAIL_TITLE+"\n"+text);
} else {
Logger.log("昨日分のレビューがないのでメール送信はしませんでした。");
}
}
// 1シート分の処理
function jobSheet(type, sheetName)
{
var ROW_START = 2; //IDが入っている行の開始位置
var COL_ID = 2; //IDが入っている列
var COL_LAST = 7; //最終取得日を入れる列
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var range = sheet.getDataRange();
var values = range.getValues();
Logger.log("シート["+sheetName+"] 処理開始");
var cnt=0;
var text = "";
for(var i = ROW_START-1; i < values.length; i++){
var id = values[i][COL_ID-1];
var lastDate = new Date(values[i][COL_LAST-1]);
var result = jobTitle(type, id, lastDate);
text += result.text;
// エラーやundefinedでなく、レビューがあった場合、最終日更新
if (!result.error && result.text!=null && result.text.length>0) {
values[i][COL_LAST-1] = new Date(); // 最終取得日の変更
}
cnt++;
}
if (!DEBUG) {
range.setValues(values); //シート書き戻し
}
Logger.log("シート["+sheetName+"] "+cnt+"タイトル処理終了");
return text;
}
// 1タイトル分の処理
function jobTitle(type, id, lastDate)
{
var result;
var text = "";
var RETRY = 1; //リトライ回数
var retryCnt;
for (retryCnt=0; retryCnt<RETRY; retryCnt++) {
//レビューをとってくる
if (type == "AppStore") {
result = fetchReviewAppStore(id);
result.type = "AppStore";
} else {
result = fetchReviewGooglePlay(id);
result.type = "GooglePlay";
}
if (!result.error)
break;
}
//エラー
if (result.error) {
var error_text = "FetchERROR(" + result.response.getResponseCode() + ") : " + result.link + "\n";
Logger.log(error_text);
result.text = text;
return result;
}
//最終取得日から昨日までのレビューのみを抽出
var date = new Date();
date.setDate(date.getDate()-1);
result.reviews = extractReviewByDate(result.reviews, lastDate, date);
if (result.reviews.length > 0) {
//タイトル
text += "\n";
text += "■\n";
text += "■ " + result.type + " : " + result.title + "\n";
text += "■ " + result.link + "\n";
text += "■\n";
text += "\n";
//レビューを新しい順にソートして追加
result.reviews.sort((function(a,b){return(new Date(b.date).getTime() - new Date(a.date).getTime());}));
text += formatReview(result.reviews);
}
Logger.log(id+" "+result.title+" "+result.reviews.length+"レビュー");
result.text = text;
return result;
}
//レビューを整形
function formatReview(reviews)
{
var text = "";
for (var i in reviews) {
text = text + reviews[i].date + " " + reviews[i].author + "\n";
text = text + reviews[i].title + " " + ("★★★★★☆☆☆☆☆").substr(5-reviews[i].rating, 5) + "\n";
text = text + reviews[i].content + "\n";
text = text + "\n";
}
return text;
}
//指定日のレビューのみ抽出
function extractReviewByDate(reviews, dateBegin, dateEnd)
{
var result = [];
if (isNaN(dateBegin.getTime())) {
dateBegin = new Date("2000/1/1");
}
dateBegin.setHours(0);
dateBegin.setMinutes(0);
dateBegin.setSeconds(0);
dateBegin.setMilliseconds(0);
dateEnd.setHours(0);
dateEnd.setMinutes(0);
dateEnd.setSeconds(0);
dateEnd.setMilliseconds(0);
for (var i in reviews) {
var d = new Date(reviews[i].date);
d.setHours(0);
d.setMinutes(0);
d.setSeconds(0);
d.setMilliseconds(0);
if (dateBegin.getTime()<=d.getTime() && d.getTime()<=dateEnd.getTime()) {
result.push(reviews[i]);
}
}
Logger.log(dateBegin.toLocaleDateString() + " - " + dateEnd.toLocaleDateString());
return result;
}
// AppStoreからレビュー取得
function fetchReviewAppStore(id) {
var url = "https://itunes.apple.com/jp/rss/customerreviews/id=" + id + "/xml";
var query = 'select * from xml where url="' + url + '"';
var response = UrlFetchApp.fetch("https://query.yahooapis.com/v1/public/yql?format=json&q="+encodeURIComponent(query),{'muteHttpExceptions':true});
try {
var entrys = JSON.parse(response).query.results.feed.entry;
var result = {};
var review = [];
for (var entry in entrys) {
if (entry == 0) {
result.title = entrys[entry].name;
result.link = entrys[entry].link.href;
}
else {
review.push({
date: entrys[entry].updated.replace(/(.*?)-(.*?)-(.*?)T(.*?)-.*/,"$1/$2/$3 $4"),
title: entrys[entry].title,
content: entrys[entry].content[0].content,
rating: entrys[entry].rating,
version: entrys[entry].version,
author: entrys[entry].author.name
});
}
}
result.reviews = review;
result.error = false;
return result;
} catch (e) {
return {
error: true,
response: response,
title: "",
link: url,
reviews: review
};
}
}
// GooglePlayからレビュー取得
function fetchReviewGooglePlay(id) {
var url = "https://play.google.com/store/apps/details?id=" + id + "&hl=ja";
var response = UrlFetchApp.fetch(url,{'muteHttpExceptions':true});
try {
var result = {};
var review = [];
result.error = false;
var regexp = /<div class=\"id-app-title\".+?<\/div>/gi;
var elements = response.getContentText().match(regexp);
result.title = elements[0].replace(/.*?>(.*?)<.*/,"$1");
result.link = url;
var regexp = /<div class=\"single-review\".+?class=\"review-link\"/gi;
var elements = response.getContentText().match(regexp);
for (var i in elements) {
review.push({
author: elements[i].replace(/.*<span class=\"author-name\">.*?>(.*?)<.*/,"$1"),
date: elements[i].replace(/.*<span class=\"review-date\">(.*?)年(.*?)月(.*?)日.*/,"$1/$2/$3"),
title: elements[i].replace(/.*<span class=\"review-title\">(.*?)<.*/,"$1"),
content: elements[i].replace(/.*<span class=\"review-title\">.*?>(.*?)<.*/,"$1"),
rating: elements[i].replace(/.*aria-label=\"5つ星のうち(.*?)つ星で評価しました.*/,"$1")
});
}
result.reviews = review;
result.error = false;
return result;
} catch(e) {
return {
error: true,
response: response,
title: "",
link: url,
reviews: review
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment