Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 259 lines (233 sloc) 7.169 kb
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
1 #!/usr/bin/env node
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
2
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
3 'use strict';
4
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
5 var http = require('http');
6 var https = require('https');
7 var fs = require('fs');
8
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
9 var collections = {
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
10 'guide': 'https://docs.google.com/feeds/default/private/full/folder%3A0B9PsajIPqzmANGUwMGVhZmYtMTk1ZC00NTdmLWIxMDAtZGI5YWNlZjQ2YjZl/contents',
11 'api': 'https://docs.google.com/feeds/default/private/full/folder%3A0B7Ovm8bUYiUDYjMwYTc2YWUtZTgzYy00YjIxLThlZDYtYWJlOTFlNzE2NzEw/contents',
12 'tutorial': 'https://docs.google.com/feeds/default/private/full/folder%3A0B9PsajIPqzmAYWMxYWE3MzYtYzdjYS00OGQxLWJhZjItYzZkMzJiZTRhZjFl/contents',
13 'cookbook': 'https://docs.google.com/feeds/default/private/full/folder%3A0B7Ovm8bUYiUDNzkxZWM5ZTItN2M5NC00NWIxLTg2ZDMtMmYwNDY1NWM1MGU4/contents',
14 'misc': 'https://docs.google.com/feeds/default/private/full/folder%3A0B7Ovm8bUYiUDZjVlNmZkYzQtMjZlOC00NmZhLWI5MjAtMGRjZjlkOGJkMDBi/contents'
d6e4636 Vojta Jina Couple of missing semi-colons
vojtajina authored
15 };
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
16
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
17 console.log('Google Docs...');
18
19 var flag = process && process.argv[2];
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
20 if (flag == '--login') {
21 var username = process.argv[3];
22 if (username) {
23 askPassword(function(password){
24 login(username, password);
25 });
26 } else {
27 console.log('Missing username!');
28 }
29 } else if (flag == '--fetch') {
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
30 var collection = process.argv[3];
31 if (collection) {
32 fetch(collection, collections[collection]);
33 } else {
34 for (collection in collections)
35 fetch(collection, collections[collection]);
36 }
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
37 } else {
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
38 help();
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
39 }
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
40
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
41 function help() {
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
42 console.log('Synopsys');
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
43 console.log('gdocs.js --login <username>');
44 console.log('gdocs.js --fetch [<docs collection>]');
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
45 process.exit(-1);
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
46 }
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
47
48
91f9efe Igor Minar gdocs.js should store files under docs/content/[collection]/
IgorMinar authored
49 function fetch(collection, url){
50 console.log('fetching a list of docs in collection ' + collection + '...');
887da56 Igor Minar enhancing gdocs.js to work with nested collections
IgorMinar authored
51 request('GET', url, {
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
52 headers: {
53 'Gdata-Version': '3.0',
54 'Authorization': 'GoogleLogin auth=' + getAuthToken()
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
55 }
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
56 },
57 function(chunk){
58 var entries = chunk.split('<entry');
59 entries.shift();
60 entries.forEach(function(entry){
61 var title = entry.match(/<title>(.*?)<\/title>/)[1];
62 if (title.match(/\.ngdoc$/)) {
63 var exportUrl = entry.match(/<content type='text\/html' src='(.*?)'\/>/)[1];
64 download(collection, title, exportUrl);
65 }
66 });
67 }
68 );
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
69 }
70
91f9efe Igor Minar gdocs.js should store files under docs/content/[collection]/
IgorMinar authored
71 function download(collection, name, url) {
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
72 console.log('Downloading:', name, '...');
73 request('GET', url + '&exportFormat=txt',
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
74 {
75 headers: {
76 'Gdata-Version': '3.0',
77 'Authorization': 'GoogleLogin auth=' + getAuthToken()
78 }
79 },
80 function(data){
81 data = data.replace('\ufeff', '');
82 data = data.replace(/\r\n/mg, '\n');
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
83
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
84 // strip out all text annotations
85 data = data.replace(/\[[a-zA-Z]{1,2}\]/mg, '');
a4dd9ca Igor Minar fix comment stripping
IgorMinar authored
86
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
87 // strip out all docos comments
88 data = data.replace(/^[^\s_]+:\n\S+[\S\s]*$/m, '');
22dee3e Igor Minar gdocs.js - add docos style comment stripping
IgorMinar authored
89
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
90 // fix smart-quotes
91 data = data.replace(/[“”]/g, '"');
92 data = data.replace(/[‘’]/g, "'");
fd6e5e3 Miško Hevery replace smart-quotes with regular quotes
mhevery authored
93
94
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
95 data = data + '\n';
d428c99 Replaced double line break with single when text is fetched from Google ...
Di Peng authored
96
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
97 //this should be a bug in Google Doc API, hence need to remove this once the bug is fixed
98 data = data.replace(/\n\n/g, '\n');
d428c99 Replaced double line break with single when text is fetched from Google ...
Di Peng authored
99
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
100 fs.writeFileSync('docs/content/' + collection + '/' + name, reflow(data, 100));
101 }
102 );
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
103 }
104
105 /**
106 * token=$(curl
107 * -s https://www.google.com/accounts/ClientLogin
108 * -d Email=...username...
109 * -d Passwd=...password...
110 * -d accountType=GOOGLE
111 * -d service=writely
112 * -d Gdata-version=3.0 | cut -d "=" -f 2)
113 */
114 function login(username, password){
115 request('POST', 'https://www.google.com/accounts/ClientLogin',
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
116 {
117 data: {
118 Email: username,
119 Passwd: password,
120 accountType: 'GOOGLE',
121 service: 'writely',
122 'Gdata-version': '3.0'
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
123 },
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
124 headers: {
125 'Content-type': 'application/x-www-form-urlencoded'
126 }
127 },
128 function(chunk){
129 var token;
130 chunk.split('\n').forEach(function(line){
131 var parts = line.split('=');
132 if (parts[0] == 'Auth') {
133 token = parts[1];
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
134 }
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
135 });
136 if (token) {
137 fs.writeFileSync('tmp/gdocs.auth', token);
138 console.log("logged in, token saved in 'tmp/gdocs.auth'");
139 } else {
140 console.log('failed to log in');
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
141 }
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
142 }
143 );
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
144 }
145
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
146 function getAuthToken() {
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
147 var pwdFile = 'tmp/gdocs.auth';
148 try {
149 fs.statSync(pwdFile);
150 return fs.readFileSync(pwdFile);
151 } catch (e) {
152 console.log('Please log in first...');
153 }
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
154 }
155
156 function request(method, url, options, response) {
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
157 url = url.match(/http(s?):\/\/(.+?)(\/.*)/);
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
158 var isHttps = url[1];
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
159 var req = (isHttps ? https : http).request({
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
160 host: url[2],
161 port: (url[1] ? 443 : 80),
162 path: url[3],
163 method: method
164 }, function(res){
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
165 var data;
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
166 switch (res.statusCode) {
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
167 case 200:
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
168 data = [];
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
169 res.setEncoding('utf8');
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
170 res.on('end', function () { response(data.join('')); });
171 res.on('close', function () { response(data.join('')); }); // https
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
172 res.on('data', function (chunk) { data.push(chunk); });
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
173 res.on('error', function (e) { console.log(e); });
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
174 break;
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
175 case 401:
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
176 console.log('Eror: Login credentials expired! Please login.');
177 break;
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
178 default:
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
179 data = [];
29d36e9 Miško Hevery feat(gdocs): better error handling
mhevery authored
180 console.log('ERROR: ', res.statusCode);
181 console.log('REQUEST URL: ', url[0]);
182 console.log('REQUEST POST: ', options.data);
183 console.log('REQUEST HEADERS: ', options.headers);
184 console.log('RESPONSE HEADERS: ', res.headers);
185 res.on('end', function (){ console.log('BODY: ', data.join('')); });
186 res.on('close', function (){ console.log('BODY: ', data.join('')); }); // https
187 res.on('data', function (chunk) { data.push(chunk); });
188 res.on('error', function (e){ console.log(e); });
c763b00 Miško Hevery feat(gdocs.js): output usefull error messages when not logged in.
mhevery authored
189 }
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
190 });
191 for(var header in options.headers) {
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
192 req.setHeader(header, options.headers[header]);
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
193 }
194 if (options.data)
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
195 req.write(encodeData(options.data));
196 req.on('end', function() {
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
197 console.log('end');
198 });
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
199 req.end();
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
200 }
201
202 function encodeData(obj) {
203 var pairs = [];
204 for(var key in obj) {
205 pairs.push(key + '=' + obj[key]);
206 }
207 return pairs.join('&') + '\n';
208 }
209
210 function askPassword(callback) {
211 var stdin = process.openStdin(),
212 stdio = process.binding("stdio");
213
214 stdio.setRawMode();
215
216 console.log('Enter your password:');
d6e4636 Vojta Jina Couple of missing semi-colons
vojtajina authored
217 var password = "";
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
218 stdin.on("data", function(c) {
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
219 c = c + "";
220 switch (c) {
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
221 case "\n":
222 case "\r":
223 case "\u0004":
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
224 stdio.setRawMode(false);
225 stdin.pause();
226 callback(password);
227 break;
228 case "\u0003":
229 process.exit();
230 break;
231 default:
232 password += c;
233 break;
234 }
36831ec Michał Gołębiowski refactor(jshint): reduce duplication & test all JS files
mzgol authored
235 });
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
236
237 }
238
239 function reflow(text, margin) {
240 var lines = [];
241 text.split(/\n/).forEach(function(line) {
242 var col = 0;
243 var reflowLine = '';
fd822bd Miško Hevery chore(formating): clean code to be function() {
mhevery authored
244 function flush() {
08e3b1e Igor Minar gdocs.js should strip trailing whitespace in imported docs
IgorMinar authored
245 reflowLine = reflowLine.replace(/\s*$/, '');
7a54d27 Miško Hevery script for dowlnoading docs from google docs
mhevery authored
246 lines.push(reflowLine);
247 reflowLine = '';
248 col = 0;
249 }
250 line.replace(/\s*\S*\s*/g, function(chunk){
251 if (col + chunk.length > margin) flush();
252 reflowLine += chunk;
253 col += chunk.length;
254 });
255 flush();
256 });
257 return lines.join('\n');
258 }
Something went wrong with that request. Please try again.