Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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