-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgrapevine.js
More file actions
322 lines (301 loc) · 11.3 KB
/
Copy pathgrapevine.js
File metadata and controls
322 lines (301 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
// grapevine setup
var https = require('https');
var http = require('http');
var socks = require('socksv5');
var countries_json = require('./countries.json');
var googleApiKey = require('./api_key.json');
var exec = require('child_process').exec;
var querystring = require('querystring');
var striptags = require('striptags');
var log4js = require('log4js');
var parser = require('xml2json');
var cheerio = require('cheerio');
var striptags = require('striptags');
log4js.configure({
appenders: [
// { type: 'console' },
{ type: 'file', filename: 'grapevine.log' }
]
});
var logger = log4js.getLogger();
var grapevine = {
countries: countries_json,
base_socks_port: 9050,
base_control_port: 15000,
API_KEY: googleApiKey.key,
// setting this to true makes everything use a single tor instance on port 9050
// instead of a different tor instance for each country
debug: true,
init: function(callback) {
if (this.debug) {
return callback();
}
var that = this;
// kill all tor instances
exec('killall tor', function(error, stdout, stderr) {
if (error) {
// rn('No tor instances to kill');
// rn(error);
}
var i = 1;
var j = 0;
console.log("that.countries: ");
console.log(that.countries);
for (key in that.countries) {
var socksPort = that.base_socks_port + i;
var controlPort = that.base_control_port + i;
that.countries[key].socksPort = socksPort;
that.countries[key].controlPort = controlPort;
var pidFilename = 'tor' + i + '.pid';
var dataDirectory = 'tor_data/tor' + i;
var exitNode = '{' + key.toLowerCase() + '}';
var torCommand = 'tor --RunAsDaemon 1 --PidFile ' + pidFilename + ' --SocksPort ' + socksPort + ' --DataDirectory ' + dataDirectory + ' --ExitNodes ' + exitNode;
i++;
exec(torCommand, function(error, stdout, stderr){
if (error) {
// warn('tor command failed: ' + torCommand);
// logger.warn(error);
}
else {
// info('Successfully connected via ' + torCommand.substring(torCommand.length - 3));
}
j++;
if (j >= Object.keys(that.countries).length)
{
callback();
}
});
}
});
},
//https call to google translate API
translate: function(search_query, from_language, to_language, callback){
if (from_language.toLowerCase() == to_language.toLowerCase()) {
return callback(search_query);
}
// URL encode the search string
search_query = querystring.escape(search_query);
var httpOptions = {
host: 'www.googleapis.com',
port: 443,
// path: '/language/translate/v2?key=' + this.API_KEY + '&source=' + from_language + '&target=' + to_language + '&q=' + search_query,
path: '/language/translate/v2?key=' + this.API_KEY + '&q=' + search_query + '&source=' + from_language + '&target=' + to_language,
method: 'GET'
};
// logger.debug("translation path: ", httpOptions.host + httpOptions.path);
var request = https.request(httpOptions, function(response) {
// logger.debug("response data: ", response);
// logger.debug("statusCode: ", response.statusCode);
// logger.debug("headers: ", response.headers);
var response_string = '';
response.on('data', function(d) {
response_string += d;
// logger.debug('response_string: ', response_string);
});
response.on('end', function() {
var translation;
// logger.info("response_string: ", response_string);
var response_data = JSON.parse(response_string).data;
if (response_data) {
translation = response_data.translations[0].translatedText;
}
else {
translation = 'No translation available.';
}
callback(translation);
});
response.on('error', function(err) {
logger.warn('Error receiving translation api response: ' + err);
logger.warn('Trying again');
logger.warn('Is google translate working?');
grapevine.translate(search_query, from_language, to_language, callback);
});
});
request.end();
request.on('error', function(err) {
// logger.warn('Error sending translation api request: ' + err);
// er.warn('Trying again');
grapevine.translate(search_query, from_language, to_language, callback);
});
},
// hit news api with search term, sending request thru appropriate tor instance
get_news_about: function(search_query, country_code, language_code, result_start, callback){
// URL encode the search string
search_query = querystring.escape(search_query);
var torPort;
if (this.debug)
{
torPort = 9050;
}
else
{
torPort = this.countries[country_code].socksPort;
}
// var torPort = 9050;
// logger.info('getting news about ' + search_query + ' from country ' + country_code);
// tor config
var socksConfig = {
proxyHost: '127.0.0.1',
proxyPort: torPort,
auths: [ socks.auth.None() ]
};
// request config
var httpOptions = {
host: 'news.google.com',
port: 443,
// path: '/ajax/services/search/news?v=1.0&ned=' + country_code + '&start=' + result_start + '&rsz=8&hl=' + language_code + '&q=' + search_query,
path: '/news/feeds?pz=1&cf=all&ned='+language_code+'&hl='+country_code+'&q='+search_query+'&output=rss',
method: 'GET',
agent: new socks.HttpsAgent(socksConfig)
};
logger.info(httpOptions.host + httpOptions.path);
var request = https.request(httpOptions, function(response) {
logger.info('response.data = ', response.data);
response.resume();
var response_string = '';
response.on('data', function(d) {
response_string += d;
});
response.on('end', function() {
// var response_json = JSON.parse(response_string);
// logger.info("response_string: ", response_string);
callback(response_string);
});
response.on('error', function(err) {
logger.warn('Error receiving news api response: ' + err);
logger.warn('Trying again');
logger.warn('Is google news apis working?');
get_news_about(search_query, country_code, language_code, result_start, callback);
});
});
request.end();
request.on('error', function(err) {
logger.warn('Error sending news api request: ' + err);
logger.warn('Trying again');
logger.warn('Is google apis working?');
get_news_about(search_query, country_code, language_code, result_start, callback);
});
},
check_ip_for_country: function(country_code, callback)
{
var country = this.countries[country_code];
if (country === undefined) {
// logger.error('No country found for country code: ' + country_code);
return;
}
// should derive torPort from country_code
// var torPort = 9050;
var torPort = country.socksPort;
var socksConfig = {
proxyHost: '127.0.0.1',
proxyPort: torPort,
auths: [ socks.auth.None() ]
};
var httpOptions = {
// this is ip of "whatsmyip" server
host: '130.211.135.85',
port: 80,
path: '/',
method: 'GET',
agent: new socks.HttpAgent(socksConfig)
};
var req = http.request(httpOptions, function(res) {
res.resume();
var response_string = '';
res.on('data', function(d) {
response_string += d;
});
res.on('end', function() {
var json = JSON.parse(response_string);
var exit_node_country = json.country;
callback(exit_node_country.toLowerCase().trim(), country_code.toLowerCase().trim());
});
res.on('error', function(err) {
logger.warn('Error receiving response to request' + httpOptions);
logger.warn(err);
});
});
req.end();
req.on('error', function(err) {
logger.warn('Error sending request' + httpOptions);
logger.warn(err);
});
},
simulate_country: function(search_query, country_code, from_language, result_start, callback)
{
// logger.info('Searching ' + search_query + ' from ' + country_code);
var that = this;
var sim_country_callback = callback;
var to_language = this.countries[country_code].language_code;
console.log("to_language", to_language);
this.translate(search_query, from_language, to_language, function(result){
var translation = result;
logger.info(search_query + '-->' + translation);
that.get_news_about(translation, country_code, to_language, result_start, function(result){
var news_stories = [];
var translated = 0;
// console.log("result = ", result);
var news_xml = result;
var news_json = parser.toJson(news_xml);
for(idx in JSON.parse(news_json).rss.channel.item){
var xml_news_description = JSON.parse(news_json).rss.channel.item[idx].description.split('<font size="-1">');
news_stories[idx] = {};
news_stories[idx].untranslated_title = JSON.parse(news_json).rss.channel.item[idx].title;
news_stories[idx].link = JSON.parse(news_json).rss.channel.item[idx].link;
news_stories[idx].source = striptags(xml_news_description[1]);
news_stories[idx].untranslated_summary = striptags(xml_news_description[2]);
}
var xhtmlUnescape = function(escapedXhtml) {
escapedXhtml = escapedXhtml.replace(/"/g, '"');
escapedXhtml = escapedXhtml.replace(/&/g, '&');
escapedXhtml = escapedXhtml.replace(/</g, '<');
escapedXhtml = escapedXhtml.replace(/>/g, '>');
escapedXhtml = escapedXhtml.replace(/'/g, "'");
escapedXhtml = escapedXhtml.replace(/ /g, " ");
return escapedXhtml;
};
var add_translations = function(news_stories, callback){
var news = [];
//for each news story
for(idx in news_stories){
var translated = 0;
translator(idx, function(result){
news.push(result);
if(++translated==idx){
callback(news);
}
});
}
}
var translator = function(idx, callback){
that.translate(news_stories[idx].untranslated_summary, to_language, from_language, function(result){
news_stories[idx].translated_summary = xhtmlUnescape(result);
that.translate(news_stories[idx].untranslated_title, to_language, from_language, function(result){
news_stories[idx].translated_title = xhtmlUnescape(result);
callback(news_stories[idx]);
});
});
}
//add translated versions into news stories
add_translations(news_stories, function(news){
logger.info("hello hello line 300 news_stories...", news);
// grapevine.news_stories = news_stories;
callback(news);
});
});
});
},
shutdown : function (callback)
{
// kill all tor instances
exec('killall tor', function(error, stdout, stderr) {
if (error) {
// rn(error);
// rn(stderr);
}
});
callback();
}
};
module.exports = grapevine;
//99:37:9f:8d:d6:7b:5f:f0:3a:b1:f0:8c:71:bf:0a:d1