UNPKG

28.5 kBJavaScriptView Raw
1/*
2HOTELPARTNER
3Autor: HotelPartner WDS
4Author's note: “Clean code always looks like it was written by someone who cares.” ― Robert C. Martin,
5
6Date: 16.08.2017
7Version: 2.0
8Notes: Make sure that the hostname is set correct!
9===============================
10
11 */
12
13//LIBARIES
14const parseString = require('xml2js').parseString;
15
16//HP LIBARIES
17const _HP = require("./classHotels.js");
18const _SERVER = require("./server.js");
19const slave = _SERVER.os.hostname().replace('slave','');
20
21let currentip = '0.0.0.0';
22let errjobcounter = 0;
23let client;
24let mobile;
25let hostip;
26let hostport;
27
28const hp_bot = {
29 "init":function init() {
30 setTimeout(async function(){
31 var newjob = hp_bot.job.getOldJob();
32
33 if(!newjob)
34 newjob = await hp_bot.job.getNewJob();
35 else
36 console.log("BACKUP JOB FOUND");
37
38 if(mobile==-1)
39 hp_bot.bot.standart(newjob);
40 else
41 hp_bot.bot.mobile(newjob);
42 },800)
43 },
44 "constructor":function JOB(_mobile=-1,_client='WDS',_host='192.168.56.1',_port='88') {
45
46 mobile = _mobile;
47 client = _client;
48 hostip = _host;
49 hostport = _port;
50
51 //START SERVER
52 _SERVER.start();
53 },
54 job: {
55 'getNewJob' : function getNewJob(rebootOnError=true) {
56 console.log("");
57 console.log("GETTING NEW JOB FROM DB... CLIENT:" +client );
58 let data = "";
59 let clientVersion = '2217'
60
61 return new Promise(resolve=>{
62
63 //callback with new clientversion
64 // get new Job from db
65 function _clientVersionCallB(clientversion){
66 console.log('clientversion '+clientversion)
67
68 _SERVER.http.get('http://www.yieldagent.ch/relay/cityov/requestJobV8.php?version='+clientVersion+'&client='+client, function(res) {
69 if (res.statusCode >= 200 && res.statusCode < 400)
70 {
71 res.on('data', function(data_) { data += data_.toString(); });
72 res.on('end', function() {
73 parseString(data, function (err, result) {
74
75 try
76 {
77 if (result)
78 {
79 clientVersion = result.Request.$.clientVersion;
80 _SERVER.fs.writeFile('./clientVersion.txt', clientVersion, 'utf8', function readFileCallback(err, data) {
81 if (err)
82 console.log(err);
83
84 else
85 console.log("new Client Version "+clientVersion)
86
87 });
88
89 let ids = [];
90 let city = result.Request.CityConfig[0].URLArguments[0];
91 city = city.split(';city=');
92 city.shift();
93 city.forEach(t => {
94 t = t.substr(0, t.indexOf(';'))
95 ids.push(t)
96 });
97 let job = {
98 "id": result.Request.CityConfig[0].CityID[0],
99 "cityid": ids,
100 "name": result.Request.CityConfig[0].CityName[0],
101 "dates": result.Request.Dates[0].Date,
102 "backup": result.Request.Dates[0].Date,
103 "job": result.Request.JobID[0],
104 "los": result.Request.$.los
105 };
106
107 hp_bot.job.saveJob(job);
108
109 if(!result.Request.Dates[0].Date){
110 hp_bot.general.errorHandler(job,1,moment().format('YYYY-MM-DD'),job.name,job.cityid,'{"error":"no date"}')
111 hp_bot.job.saveJob([]);
112 }
113
114 if(!result.Request.CityConfig[0].CityName[0]){
115 hp_bot.general.errorHandler(job,1,moment().format('YYYY-MM-DD'),'null',0,'{"error":"city"}')
116 hp_bot.job.saveJob([]);
117 }
118
119 resolve(job)
120 }
121 }
122 catch (TypeError)
123 {
124 setTimeout(function () {
125 _clientVersionCallB(clientversion)
126 },10000);
127 console.log("JOB parsing error")
128 console.log(result.Request)
129 console.log(" ")
130 console.log("getting new jeb with new clientVersion:" +clientVersion)
131
132
133 }
134 if(err){
135 console.log(err)
136 setTimeout(()=>{
137 _SERVER.reboot();
138 },680000)
139 }
140 });
141 });
142 }
143 }).on('error',
144 async function(err) {
145
146 //Get current bot version
147 let version = await _SERVER.version(false);
148
149 //Handle error
150 console.log("Error while fetching new Job");
151 console.log(err)
152
153 //request new ip
154 let hosturl = 'http://'+hostip+':'+hostport;
155 _SERVER.fetch(hosturl+'/newip?gateway='+slave+'&client='+client+'&job=-1&version='+version);
156
157 //check for conntection
158 // reboot
159 setTimeout(()=>
160 {
161 if(errjobcounter >=3 && rebootOnError == true)
162 _SERVER.fetch(hosturl+'/reboot?gateway='+slave+'&client='+client+'&job=error&version='+version);
163
164 else
165 _SERVER.fetch(hosturl+'/newip?gateway='+slave+'&client='+client+'&version='+version).then(newIP=>{
166 hp_bot.job.getNewJob();
167 })
168
169 errjobcounter++;
170 },30000)
171 }
172 );
173 }
174
175
176 //Read clientsversion
177 _SERVER.fs.readFile('./clientVersion.txt','utf8', function read(err, data)
178 {
179 if (err)
180 {
181 console.log('no file: clientVersion.txt')
182 _clientVersionCallB(clientVersion);
183 return;
184 }
185 else
186 {
187 clientVersion = data;
188 _clientVersionCallB(data)
189 }
190
191 });
192 })
193
194 },
195 'nextJob' : async function nextJob(callback) {
196 const newjob = await hp_bot.job.getNewJob();
197 callback(newjob);
198 },
199 'getOldJob' : function getOldJob() {
200 console.log("searching for old job");
201 try{
202 //Look for a backup file
203 const backup = JSON.parse(_SERVER.fs.readFileSync('./backup.json', 'utf8'));
204
205 //Check if the file contains valid data
206 const checkforid = backup.cityid[0];
207 const checkfordate = backup.dates[0];
208 return backup;
209 }
210 catch (TypeError)
211 {
212 console.log("no Job found..")
213 return null
214 }
215 },
216 'updateOldJob': function (date,cityid,resetdate=false) {
217
218 console.log('update Backup ');
219 let backup = JSON.parse(_SERVER.fs.readFileSync('./backup.json', 'utf8'));
220 const indx = backup.dates.indexOf(date);
221
222 //Update dates
223 if (indx > -1)
224 {
225 console.log("removing date")
226 backup.dates.splice(indx, 1);
227 }
228 //Update cityid
229 if(cityid)
230 {
231 console.log("removing city id")
232 const indx2= backup.cityid.indexOf(cityid)
233
234 if (indx2 > -1)
235 {
236 backup.cityid.splice(indx2, 1);
237 }
238 if(backup.backup)
239 {
240 backup.dates = backup.backup;
241 }
242 }
243
244 //Save the new Backup
245 hp_bot.job.saveJob(backup)
246 },
247 'saveJob' : function (json) {
248 if(!json)return;
249 console.log("Saving Job | backup.json");
250 _SERVER.fs.writeFile('./backup.json', JSON.stringify(json), 'utf8', function readFileCallback(err, data) {
251 if (err)
252 console.log(err);
253 else
254 console.log("JOB is SAVED")
255
256 });
257 }
258 },
259 bot: {
260 "mobile" : async function startMobileJob (arg) {
261 let isfetching = true;
262 console.log("->Fetching Mobile Version");
263
264 //IF NO CITY ID go to NEXT JOB
265 if(arg.cityid[0]=='' || !arg.cityid[0])
266 {
267 hp_bot.job.nextJob(startMobileJob);
268 return
269 }
270
271 console.log("JOB FOUND:");
272 console.log(arg);
273 console.log("=====================");
274 currentip = await _SERVER.showExternalIP(true)
275
276 let city = arg.name.replace(" ", '+');
277 let icity = 0;
278 let countcity = arg.cityid.length;
279
280 let idate = 0;
281 let countdate = arg.dates.length;
282 const backupdate = JSON.parse(JSON.stringify(arg.dates))
283 let tempdate;
284 let counterror = 0;
285
286 let logged = false;
287
288 nextCityId();
289 function nextCityId() {
290 //Check if we have made all CityID
291 if(icity==countcity && isfetching){
292 console.log("Job Done");
293 console.log(JSON.stringify(_HP.hotels.Booking));
294 hp_bot.job.nextJob(startMobileJob);
295 }
296 //Start fetching next CityID
297 if(icity<countcity)
298 {
299 idate=0;
300 nextDate(arg.cityid[icity])
301 icity++;
302 }
303
304 }
305 function nextDate(cityid) {
306 //Clear after new date
307 _HP.hotels.Booking = [];
308 const start = arg.dates[idate];
309 tempdate = start;
310 fetchIphoneXMLData(1,start,city,cityid);
311 idate++;
312 }
313 function fetchIphoneXMLData(adult,start,city,cityid) {
314 return new Promise(resolve=>{
315
316 const end = _SERVER.time(start).add(1, 'day').format('YYYY-MM-DD');
317 const devid = hp_bot.general.generateDeviceID(false);
318 const _url = `https://iphone-xml.booking.com/json/bookings.getHotelAvailabilityMobile?detail_level=1&genius_freebies=2&show_distance_cc=1&request_less_fields=2&show_facilities_review_score=1&show_last_minute_saving=1&include_translations=2&add_bh_info=1&languagecode=de&urgency=1&include_taxes=1&include_count=1&location_source=autocomplete&show_price_trend=1&show_deals=flash%2Clastm%2Csmart%2Cgenius&children_qty=0&low_av_alternatives=0&&&order_by=popularity&show_if_class_is_estimated=1&show_categories=v3&show_location_score=1&show_last_reservation_text=1&show_reinforcement_text=v2&show_filtered_facilities=1&show_if_no_cc_allowed=2&show_soldout=1&show_is_personalized_result=0&show_flash_saving=1&max_persons=-2&use_direct_payment=1&add_ctrip_info=1&include_rack_rate_savings=1&&include_url=1&bh_alt_urgency_msg=1&show_refundable=1&check_price_is_final=1&show_extra_charges=1&room_qty=1&show_if_city_center=1&available_rooms=0&price_buckets=100&flash_deals_amount_if_unsigned=2&show_low_availability=2&show_business_badge=1&autoextend=1&affiliate_id=337862&user_os=6.0.1&user_version=11.3.1-android&network_type=wifi&bt=1&arrival_date=${start}&departure_date=${end}&city_ids=${cityid.replace('city=', '').replace('|si=ai%2Cco%2Cci%2Cre%2Cdi', '')}&rows=5000&device_id=${devid}da-ef8edab1ad7f&guest_qty=${adult}`;
319 const options = {
320 headers: {
321 'Content-Type' : 'application/x-www-form-urlencoded',
322 'Authorization': 'Basic dGhlc2FpbnRzYnY6ZGdDVnlhcXZCeGdN'
323 },
324 url: _url,
325 timeout: 900000
326 };
327
328 _SERVER.request(options, function (err, resp, body)
329 {
330 const allresult = JSON.parse(body);
331 if(allresult && !logged)
332 {
333 console.log("check validate")
334 logged = true;
335 hp_bot.general.validateXmlResult(allresult,arg,adult,start,city,cityid);
336 }
337
338 setTimeout(()=>{
339 _HP.methods.Booking.parsemobile(allresult.result,adult,start,end,city,cityid).then(isok=>{
340
341 //go to next adult
342 if(isok==1||isok=='1'){
343 fetchIphoneXMLData(2,start,city,cityid);
344 }
345
346 //got to next date
347 //send result to server
348 if(isok==2||isok=='2')
349 {
350 //send job
351 _HP.methods.general.generateUrl(_HP.hotels.Booking,arg.job,arg.id,start,slave).then(answer=>{
352
353 console.log("SERVER ANSWER: "+answer)
354 if(answer=='OK')
355 {
356 //next cityid
357 if(idate==countdate)
358 {
359 hp_bot.job.updateOldJob(start,cityid,backupdate);
360 logged = false;
361 nextCityId()
362 }
363
364 //next date
365 if(idate<countdate){
366
367 //Go to Nekt Date
368 console.log("=> going to next date: "+idate);
369 hp_bot.job.updateOldJob(start,null,null);
370 nextDate(cityid)
371 }
372
373 }else
374 {
375 fetchIphoneXMLData(adult,start,city,cityid);
376 }
377 })
378 }
379
380 //Get new IP Address
381 if(isok==0||isok=='0')
382 {
383 //standart IP: 192.168.56.1
384 if(start == tempdate)counterror++;
385
386 //check if there is a error with the url
387 if(5<counterror)
388 {
389 let message;
390 try{
391 message = allresult.errors[0].message;
392 hp_bot.general.errorHandler(arg,adult,start,city,cityid,message,'Mobile Parser',true)
393 }catch (TypeError)
394 {
395 try {
396 if(allresult.in_city_translation)
397 hp_bot.general.errorHandler(arg,adult,start,city,cityid,'in_city_translation','Mobile Parser',true)
398
399 }catch (TypeError){}
400 }
401
402 counterror = 0;
403 }
404
405 hp_bot.general.getNewIP().then(gotNewIP=>{
406 console.log('IP changes counter : '+counterror)
407 fetchIphoneXMLData(adult,start,city,cityid);
408 })
409 }
410 })
411 },100)
412 })
413
414 })
415 }
416
417 },
418 "standart" : async function startSeleniumJOB(arg) {
419 let isfetching = true;
420 console.log("->Fetching Selenium Version");
421 console.log("Selenium is still in testing mode.. ");
422
423 //IF NO CITY ID go to NEXT JOB
424 if(arg.cityid[0]=='' || !arg.cityid[0])
425 {
426 hp_bot.job.nextJob(startSeleniumJOB);
427 return
428 }
429
430 console.log("JOB FOUND:");
431 console.log(arg);
432 console.log("=====================");
433 currentip = await _SERVER.showExternalIP(true)
434
435 let city = arg.name.replace(" ", '+');
436 let icity = 0;
437 let countcity = arg.cityid.length;
438
439 let idate = 0;
440 let countdate = arg.dates.length;
441
442
443 nextCityId();
444 function nextCityId() {
445 //Check if we have made all CityID
446 if(icity==countcity && isfetching){
447 console.log("Job Done");
448 console.log(JSON.stringify(_HP.hotels.Booking));
449 hp_bot.job.nextJob(startSeleniumJOB);
450 }
451 //Start fetching next CityID
452 if(icity<countcity)
453 {
454 idate=0;
455 nextDate(arg.cityid[icity])
456 icity++;
457 }
458
459 }
460 function nextDate(cityid) {
461 //Clear after new date
462 _HP.hotels.Booking = [];
463 const start = arg.dates[idate];
464 fetchData(1,start,city,cityid);
465 idate++;
466 }
467 function fetchData(adult,start,city,cityid) {
468
469 const end = _SERVER.time(start,'YYYY-MM-DD').add(1, 'day').format('YYYY-MM-DD');
470 let room = 1;
471 let child = 1;
472
473 _HP.methods.Booking.get(cityid,city,start,end,room,adult,child,false,arg.job,arg.id).then(result=>{
474
475 let isok = -1;
476
477 //go to next adult
478 if(isok==1||isok=='1'){
479 fetchData(2,start,city,cityid);
480 }
481
482 //got to next date
483 //send result to server
484 if(isok==2||isok=='2')
485 {
486 //send job
487 _HP.methods.general.generateUrl(_HP.hotels.Booking,arg.job,arg.id,start,slave).then(answer=>{
488
489 //next cityid
490 if(idate==countdate){
491 hp_bot.job.updateOldJob(start,cityid,arg.dates);
492 nextCityId()
493 }
494
495 //next cityid
496 if(idate<countdate){
497 //Go to Nekt Date
498 console.log("=> going to next date: "+idate);
499 hp_bot.job.updateOldJob(start,null,null);
500 nextDate(cityid)
501 }
502
503 })
504 }
505
506 //Get new IP Address
507 if(isok==0||isok=='0'){
508 //standart IP: 192.168.56.1
509 hp_bot.general.getNewIP().then(gotNewIP=>{
510 fetchData(adult,start,city,cityid);
511 })
512 }
513
514 })
515
516 }
517
518 }
519 },
520 general:{
521 "generateDeviceID": function generateDeviceID(show = false) {
522 //
523
524 let nr1 = Math.floor((Math.random() * 9999) + 1000);
525 let nr2 = Math.floor((Math.random() * 9999) + 1000);
526 let nr3 = Math.floor((Math.random() * 1) + 10);
527 if(show)
528 console.log('generateDeviceID: '+ `72331403-${nr1}-${nr2}-${nr3}`)
529
530 return `72331403-${nr1}-${nr2}-${nr3}`
531 },
532 "getNewIP": function getNewIP() {
533 return new Promise(resolve=>{
534 async function ipCallBack() {
535 try{
536
537 console.log("OPS........... IP got blocked");
538 console.log('old ip: '+currentip)
539
540 hp_bot.general.generateDeviceID(true);
541
542 let version = await _SERVER.version(false);
543 const hosturl ='http://'+hostip+':'+hostport+'/newip?gateway='+slave+'&client='+client+'&job=-1&version='+version;
544
545 _SERVER.fetch(hosturl).then(ok=>{
546 setTimeout(()=>{
547 _SERVER.showExternalIP(false).then(ip=>{
548 if(!ip)
549 setTimeout(()=>{
550 ipCallBack();
551 },1000);
552 else
553 {
554 console.log("new ip:"+ip)
555 resolve(ip)
556 }
557 });
558 },45000)
559 })
560 }
561 catch (TypeError){
562 console.log("error while getting new ip")
563 resolve('0.0.0.0')
564 }
565 }
566 ipCallBack();
567 })
568 },
569 "errorHandler": function (arg,adult,start,city,cityid,message,type='mobile',reboot=false) {
570
571 console.log( "errorHandler " + type)
572
573 const hosturl='http://'+hostip+':'+hostport+'/errorjob';
574 let log = {
575 "job" : JSON.stringify(arg.job),
576 "jobid" : arg.job.id,
577 "message": message + ',{ "cityid":'+cityid+',"city":"+'+city+'+" }',
578 "cityid" : cityid,
579 "city" : city,
580 "slave" : slave,
581 "client" : client,
582 };
583
584 hp_bot.job.saveJob([]);
585 _SERVER.request.post({
586 headers: {'content-type' : 'application/x-www-form-urlencoded'},
587 url: hosturl,
588 json: true,
589 form: {
590 data: JSON.stringify(log)
591 }
592 },
593
594 function(error, response, body){
595 // resolve(body);
596 _SERVER.fs.unlink('./backup.json');
597
598 });
599 setTimeout(()=>{
600 if(reboot)
601 _SERVER.reboot();
602 },10000)
603
604 },
605 "validateXmlResult": function (xml,arg,adult,start,city,cityid) {
606 let xmlcity = null;
607 try
608 {
609
610
611 let found = false;
612 xmlcity = xml.filter;
613
614 if(xmlcity)
615 xmlcity.forEach(fitler=>
616 {
617 if(fitler.id == 'city')
618 {
619 if( fitler.categories)
620 fitler.categories.forEach(ccity=>{
621 if(ccity.name==city.replace('+',' '))
622 {
623 found = ccity
624 }
625 })
626 }
627 });
628
629 if(found==false)
630 {
631 let message = {'error':'city_ids did not match cityname '+city}
632 hp_bot.general.errorHandler(arg,adult,start,city,cityid,message,'Mobile Parser')
633 }
634 else
635 {
636 console.log("Data is valid")
637 }
638
639 }
640 catch (TypeError){
641 console.log(" error validate date")
642 console.log(xmlcity)
643 console.log(TypeError)
644 }
645
646 }
647 }
648};
649
650
651//EXPORT
652hp_bot.constructor.prototype.start = hp_bot.init;
653hp_bot.constructor.prototype.getNewJob = hp_bot.job.getNewJob;
654module.exports = hp_bot.constructor;
\No newline at end of file