Skip to content

Instantly share code, notes, and snippets.

@binux
Last active December 14, 2015 17:39
Show Gist options
  • Save binux/5123568 to your computer and use it in GitHub Desktop.
Save binux/5123568 to your computer and use it in GitHub Desktop.
Google App Script of reader2plus A script record user's Google reader starred items as activities.
//
// 1. Depoly as web app (https://developers.google.com/apps-script/execution_web_apps#deploying)
// 2. register as web app through the APIs Console (https://code.google.com/apis/console#access)
// 3. add 'client_id', 'client_secret' to project properties.
// 4. If published to anyone else, make sure they access to the code. (https://developers.google.com/apps-script/execution_time_triggers)
//
var script_url = ScriptApp.getService().getUrl();
var client_id = ScriptProperties.getProperty('client_id');
var client_secret = ScriptProperties.getProperty('client_secret');
var scope = "https://www.googleapis.com/auth/plus.login http://www.google.com/reader/api";
var activity_types = ["http://schemas.google.com/AddActivity", "http://schemas.google.com/BuyActivity", "http://schemas.google.com/CheckInActivity",
"http://schemas.google.com/CommentActivity", "http://schemas.google.com/CreateActivity", "http://schemas.google.com/DiscoverActivity",
"http://schemas.google.com/ListenActivity", "http://schemas.google.com/ReserveActivity", "http://schemas.google.com/ReviewActivity" ];
var request_visible_actions = "http://schemas.google.com/DiscoverActivity http://schemas.google.com/AddActivity";
function doGet(request) {
if (request && request.parameter && request.parameter.logout) {
logout();
return HtmlService.createHtmlOutput('done <a href="'+script_url+'">continue</a>');
}
if (request && request.parameter && request.parameter.state == 'gplus' && request.parameter.code) {
var result = get_token(request.parameter.code);
welcome_moment();
do_update();
reset_tigger();
return result;
}
if (UserProperties.getProperty('gplus_access_token')) {
return status();
}
return HtmlService.createTemplateFromFile('index').evaluate();
}
function get_auth_url() {
return "https://accounts.google.com/o/oauth2/auth?"
+"scope="+encodeURIComponent(scope)
+"&state="+encodeURIComponent("gplus")
+"&redirect_uri="+encodeURIComponent(script_url)
+"&response_type=code&access_type=offline"
+"&client_id="+encodeURIComponent(client_id)
+'&request_visible_actions='+encodeURIComponent(request_visible_actions)
}
function get_token(code) {
var payload = {
"code" : code,
"client_id" : client_id,
"client_secret" : client_secret,
"redirect_uri" : script_url,
"grant_type" : "authorization_code"
};
var options = {
"method" : "post",
"payload" : payload
};
var response = UrlFetchApp.fetch('https://accounts.google.com/o/oauth2/token', options);
var token = Utilities.jsonParse(response.getContentText());
for (var key in token) {
UserProperties.setProperty('gplus_'+key, token[key]);
}
UserProperties.setProperty('gplus_token_expire', ((new Date()).getTime()+token.expires_in*1000).toString());
return HtmlService.createHtmlOutput('done <a href="'+script_url+'">continue</a>');
}
function gplus_request(url, data) {
if (!UserProperties.getProperty('gplus_access_token')) {
return false;
}
if (UserProperties.getProperty('gplus_token_expire') <= (new Date()).getTime() && !refresh_token()) {
return false;
}
var options = {
"method": data ? "POST" : "GET",
"payload": data ? Utilities.jsonStringify(data) : "",
"contentType": "application/json",
"headers" : {
"Authorization" : "Bearer " + UserProperties.getProperty('gplus_access_token')
},
"muteHttpExceptions": true,
};
var response = UrlFetchApp.fetch(url, options);
response = Utilities.jsonParse(response.getContentText());
return response;
}
function refresh_token() {
if (!UserProperties.getProperty('gplus_refresh_token')) {
logout();
return false;
}
var payload = {
"refresh_token" : UserProperties.getProperty('gplus_refresh_token'),
"client_id" : client_id,
"client_secret" : client_secret,
"grant_type" : "refresh_token"
};
var options = {
"method" : "post",
"payload" : payload
};
try {
var response = UrlFetchApp.fetch('https://accounts.google.com/o/oauth2/token', options);
Logger.log(response.getContentText());
var token = Utilities.jsonParse(response.getContentText());
for (var key in token) {
UserProperties.setProperty('gplus_'+key, token[key]);
}
UserProperties.setProperty('gplus_token_expire', ((new Date()).getTime()+token.expires_in*1000).toString());
return true;
} catch (e) {
Logger.log(e.message);
logout();
return false;
}
}
function verify_token() {
var options = {
"muteHttpExceptions": true,
};
var response = UrlFetchApp.fetch('https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='+UserProperties.getProperty('gplus_access_token'), options);
response = Utilities.jsonParse(response.getContentText());
if (response.error) {
return false;
} else {
UserProperties.setProperty('gplus_token_expire', ((new Date()).getTime()+response.expires_in*1000).toString());
return true;
}
}
function logout() {
var triggers = ScriptApp.getScriptTriggers();
for (var i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
var options = {
"muteHttpExceptions": true,
};
UrlFetchApp.fetch("https://accounts.google.com/o/oauth2/revoke?token="+UserProperties.getProperty('gplus_access_token'), options);
UserProperties.deleteAllProperties();
}
<html>
<body>
<a href="<?= get_auth_url() ?>"><img src="https://developers.google.com/+/images/branding/sign-in-buttons/Red-signin_Medium_base_44dp.png" /></a>
</body>
</html>
function reset_tigger() {
var triggers = ScriptApp.getScriptTriggers();
for (var i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("do_update")
.timeBased()
.everyMinutes(5)
.create();
}
function welcome_moment() {
var moment = {
"type": "http://schemas.google.com/AddActivity",
"target": {
"id": "welcome-moment",
"type":"http://schemas.google.com/AddActivity",
"name": "reader2plus is now working",
"description": "A script record user's Google reader starred items as activities.",
},
};
var response = gplus_request("https://www.googleapis.com/plus/v1/people/me/moments/vault", moment);
}
function status() {
return HtmlService.createTemplateFromFile('status').evaluate();
}
function do_update() {
var reader;
if (UserProperties.getProperty('last_update')) {
reader = gplus_request("https://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/starred?n=100&ot="+UserProperties.getProperty('last_update'));
} else {
reader = gplus_request("https://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/starred?n=1");
}
UserProperties.setProperty("last_update", parseInt((new Date()).getTime() / 1000).toString());
var sheet = get_sheet();
var scriptdb = ScriptDb.getMyDb();
reader.items.forEach(function(e) {
if (e.alternate.length <= 0 || !e.alternate[0].href) return ;
if (scriptdb.query({"id": e.id}).getSize() > 0) return;
var moment = {
"type": "http://schemas.google.com/DiscoverActivity",
"target": {
"url": e.alternate[0].href,
},
};
var response = gplus_request("https://www.googleapis.com/plus/v1/people/me/moments/vault", moment);
if (response.id) {
scriptdb.save({'id': e.id});
}
sheet.appendRow([e.origin.title, e.id, e.alternate[0].href, e.title, response.id]);
});
}
function get_sheet() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
if (sheet) {
return sheet;
} else if (UserProperties.getProperty('sheet')) {
sheet = SpreadsheetApp.openById(UserProperties.getProperty('sheet'));
} else {
sheet = SpreadsheetApp.create('reader2plus');
UserProperties.setProperty('sheet', sheet.getId());
}
return sheet;
}
<html>
<body>
<?
var reader_user = gplus_request('https://www.google.com/reader/api/0/user-info');
var me = gplus_request("https://www.googleapis.com/plus/v1/people/me");
?>
<?= reader_user.userEmail ?> => <a href="<?= me.url ?>" target=_blank>+<?= me.displayName ?></a> <a href="<?= script_url ?>?logout=1">logout</a>
<hr />
last updatetime: <?= UserProperties.getProperty('last_update') ?> (<?= (new Date()).getTime() / 1000 - UserProperties.getProperty('last_update') ?>s ago)
<a href="#" onclick="google.script.run.do_update();return false;">update now</a>
<br />
<a href="<?= get_sheet().getUrl() ?>" target="_blank">log sheet</a><br />
<a href="#" onclick="document.getElementById('debug_area').setAttribute('style', '')">show debug</a>
<div id="debug_area" style="display: none;">
<p>
trigger:
<a href="#" onclick="google.script.run.reset_tigger();return false;">reset tigger</a> <br />
<? for (var t = ScriptApp.getScriptTriggers(), i = 0; i < t.length; ++i) { ?>
<?= t[i].getHandlerFunction() ?> <?= t[i].getEventType() ?> <?= t[i].getUniqueId() ?><br />
<? } ?>
</p>
<p>
UserProperties:<br />
<a href="#" onclick="google.script.run.refresh_token();return false;">refresh_token</a> <br />
<? var p = UserProperties.getProperties(); for (var key in p) { ?>
<?= key ?> = <?= p[key] ?> <br />
<? } ?>
</p>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment