diff options
Diffstat (limited to 'gdocs.js')
| -rwxr-xr-x | gdocs.js | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/gdocs.js b/gdocs.js new file mode 100755 index 00000000..4507931d --- /dev/null +++ b/gdocs.js @@ -0,0 +1,199 @@ +#!/usr/bin/env node +var http = require('http'); +var https = require('https'); +var fs = require('fs'); + +console.log('Google Docs...'); + +var flag = process && process.argv[2]; +if (flag == '--login') + askPassword(function(password){ + login(process.argv[3], password); + }); +else if (flag == '--fetch') + fetch(); +else + help(); + +function help(){ + console.log('Synopsys'); + console.log('gdocs.js [--login|--fetch]'); + process.exit(-1); +}; + + +function fetch(){ + //https://docs.google.com/feeds/default/private/full/folder%3Afolder_id/contents + console.log('fetching a list of docs...'); + request('GET', 'http://docs.google.com/feeds/default/private/full/folder%3A0B7Ovm8bUYiUDZDJmNzI3NjItODY1NS00YTg3LWE2MDItNmMyODE4MDdhNDFk/contents', { + headers: { + 'Gdata-Version': '3.0', + 'Authorization': 'GoogleLogin auth=' + getAuthToken() + } + }, + function(chunk){ + var entries = chunk.split('<entry'); + entries.shift(); + entries.forEach(function(entry){ + var title = entry.match(/<title>(.*?)<\/title>/)[1]; + if (title.match(/\.ngdoc$/)) { + var exportUrl = entry.match(/<content type='text\/html' src='(.*?)'\/>/)[1]; + download(title, exportUrl); + } + }); + } + ); +} + +function download(name, url) { + console.log('Downloading:', name, '...'); + request('GET', url + '&exportFormat=txt', + { + headers: { + 'Gdata-Version': '3.0', + 'Authorization': 'GoogleLogin auth=' + getAuthToken() + } + }, + function(data){ + data = data.replace('\ufeff', ''); + data = data.replace(/\r\n/mg, '\n'); + + // strip out all text annotation comments + data = data.replace(/^\[a\][\S\s]*/m, ''); + + // strip out all text annotations + data = data.replace(/\[\w{1,3}\]/mg, ''); + + data = data + '\n'; + fs.writeFileSync('docs/' + name, reflow(data, 100)); + } + ); +} + +/** + * token=$(curl + * -s https://www.google.com/accounts/ClientLogin + * -d Email=...username... + * -d Passwd=...password... + * -d accountType=GOOGLE + * -d service=writely + * -d Gdata-version=3.0 | cut -d "=" -f 2) + */ +function login(username, password){ + request('POST', 'https://www.google.com/accounts/ClientLogin', + { + data: { + Email: username, + Passwd: password, + accountType: 'GOOGLE', + service: 'writely', + 'Gdata-version': '3.0' + }, + headers: { + 'Content-type': 'application/x-www-form-urlencoded' + } + }, + function(chunk){ + var token; + chunk.split('\n').forEach(function(line){ + var parts = line.split('='); + if (parts[0] == 'Auth') { + token = parts[1]; + } + }); + if (token) { + fs.writeFileSync('tmp/gdocs.auth', token); + console.log("logged in, token saved in 'tmp/gdocs.auth'"); + } else { + console.log('failed to log in'); + } + } + ); +} + +function getAuthToken(){ + return fs.readFileSync('tmp/gdocs.auth'); +} + +function request(method, url, options, response) { + var url = url.match(/http(s?):\/\/(.+?)(\/.*)/); + var request = (url[1] ? https : http).request({ + host: url[2], + port: (url[1] ? 443 : 80), + path: url[3], + method: method + }, function(res){ + var data = []; + res.setEncoding('utf8'); + res.on('end', function(){ + response(data.join('')); + }); + res.on('data', function (chunk) { + data.push(chunk); + }); + }); + for(var header in options.headers) { + request.setHeader(header, options.headers[header]); + } + if (options.data) + request.write(encodeData(options.data)); + request.on('end', function(){ + console.log('end'); + }); + request.end(); +} + +function encodeData(obj) { + var pairs = []; + for(var key in obj) { + pairs.push(key + '=' + obj[key]); + } + return pairs.join('&') + '\n'; +} + +function askPassword(callback) { + var stdin = process.openStdin(), + stdio = process.binding("stdio"); + + stdio.setRawMode(); + + console.log('Enter your password:'); + var password = "" + stdin.on("data", function (c) { + c = c + ""; + switch (c) { + case "\n": case "\r": case "\u0004": + stdio.setRawMode(false); + stdin.pause(); + callback(password); + break; + case "\u0003": + process.exit(); + break; + default: + password += c; + break; + } + }) + +} + +function reflow(text, margin) { + var lines = []; + text.split(/\n/).forEach(function(line) { + var col = 0; + var reflowLine = ''; + function flush(){ + lines.push(reflowLine); + reflowLine = ''; + col = 0; + } + line.replace(/\s*\S*\s*/g, function(chunk){ + if (col + chunk.length > margin) flush(); + reflowLine += chunk; + col += chunk.length; + }); + flush(); + }); + return lines.join('\n'); +} |
