add proper error handling for all final exec calls
[hband-tools.git] / óraállás-diktáló / nkmaram.js
blob80d4d96e9372c6fdb79ac186ab9e76b7576dddd0
1 #!/usr/bin/env phantomjs2 --ssl-protocol=any --ignore-ssl-errors=true --web-security=false
3 /*
4         EXIT CODE
5         0       report successful
6         1       a web interaction step failed on user side
7         2       wrong invocation
8         3       page load failed
9         4       a web interaction step failed on navigator side
10         5       report failed
13 //TODO factor out
14 var llDebug = 1, llVerbose = 2, llError = 3, llMsg = 4;
15 var vlDebug = false;
16 var vlVerbose = false;
17 var vlError = true;
18 var vlMsg = true;
19 var system = require('system');
20 var stderr = system.stderr;
21 var stdout = system.stdout;
22 var Glob = {
23         'show_history_only': false,
26 for(var i=1; i<system.args.length; i++)
28         if(system.args[i] == '--debug') vlDebug = true;
29         else if(system.args[i] == '--verbose') vlVerbose = true;
30         else if(system.args[i] == '--history') Glob.show_history_only = true;
31         else if(system.args[i].match(/^-/))
32         {
33                 stderr.write("Unknown option: "+system.args[i]+"\n");
34                 phantom.exit(2);
35         }
36         else
37         {
38                 if(!Glob.felhasznalo)
39                 {
40                         Glob.felhasznalo = system.args[i];
41                 }
42                 else if(!Glob.jelszo)
43                 {
44                         Glob.jelszo = system.args[i];
45                 }
46                 else
47                 {
48                         if(system.args[i].match(/^[0-9]+$/))
49                         {
50                                 if(typeof Glob.oraallas == "undefined") Glob.oraallas = [];
51                                 Glob.oraallas.push(system.args[i]);
52                         }
53                         else
54                         {
55                                 stderr.write("Invalid óraállás: "+system.args[i]+"\n");
56                                 phantom.exit(2);
57                         }
58                 }
59         }
62 if(!Glob.oraallas && !Glob.show_history_only)
64         stderr.write("Usage: nkmaram.js [--debug] [--verbose] <felhasználó-azonosító> <jelszó> [--history | <mérőállás-1> [<mérőállás-2> ...]]\n");
65         phantom.exit(2);
70 var url_form = "https://www.mvmnext.hu/aram/pages/wrapper.jsp?id=740&ebillCmd=login";
71 Glob.url_history = "https://www.mvmnext.hu/aram/pages/online/korabbiMeroAllOnlineUsz.jsf?id=1300460";
72 Glob.url_report = "https://www.mvmnext.hu/aram/meroallas/?id=1300461";
73 var loadInProgress = false;
74 var stepindex = 0;
75 var page = new WebPage();
76 page.settings.userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.90 Safari/537.36 Vivaldi/1.91.867.38";
78 function log(level, msg)
80         if(level == llDebug && vlDebug || 
81            level == llVerbose && vlVerbose ||
82            level == llError && vlError ||
83            level == llMsg && vlMsg)
84         {
85                 stderr.write(msg + "\n");
86         }
89 page.onConsoleMessage = function(msg)
91         if(msg.match(/^\[DEBUG\]/))
92                 log(llDebug, msg);
93         else if(msg.match(/^\[ERROR\]/))
94                 log(llError, msg);
95         else
96                 log(llMsg, ">>> " + msg);
99 page.onLoadStarted = function()
101         loadInProgress = true;
102         log(llVerbose, "load started [" + page.url + "]");
105 page.onLoadFinished = function()
107         loadInProgress = false;
108         log(llVerbose, "load finished <" + page.evaluate(function(){return document.title;}) + "> [" + page.url + "]");
111 page.onError = function(msg, stack)
113         log(llError, "ERROR: " + msg + "\nSTACK: " + JSON.stringify(stack));
116 page.onResourceRequested = function(requestData, networkRequest)
118         if(!requestData.url.match(/^data:/))
119         {
120                 log(llDebug, requestData.method+' '+requestData.url);
121         }
122         /*
123         for(var i=0; i<requestData.headers.length; i++)
124         {
125                 log(llDebug, requestData.headers[i].name + ': ' + requestData.headers[i].value);
126         }
127         log(llDebug, JSON.stringify(requestData));
128         */
132 /* Define common functions used in webpage */
133 Glob.clickFunc = '(function(elem)'+
134 '{'+
135 '       var ev = document.createEvent("MouseEvent");'+
136 '       ev.initMouseEvent("click", true /* bubble */, true /* cancelable */, window, null, 0, 0, 0, 0, /* coordinates */ false, false, false, false, /* modifier keys */ 0 /*left*/, null);'+
137 '       elem.dispatchEvent(ev);'+
138 '})';
141 page.open(url_form, function(status)
143         if(status !== 'success')
144         {
145                 log(llError, "ERROR " + status);
146                 phantom.exit(3);
147         }
148         else
149         {
150                 var steps = [
151                         function(param)
152                         {
153                                 /* Waiting page to load */
154                                 var field_user = document.querySelector('.loginForm input[name=user]');
155                                 if(!field_user)
156                                 {
157                                         //console.log(document.querySelectorAll('html')[0].outerHTML);
158                                         console.log("Waiting for login field...");
159                                         return 0;
160                                 }
161                                 return 1;
162                         },
163                         function(param)
164                         {
165                                 /* Filling in form fields and submit */
166                                 
167                                 var field_user = document.querySelector('.loginForm input[name=user]');
168                                 var field_pass = document.querySelector('.loginForm input[name=password]');
169                                 
170                                 field_user.value = param.felhasznalo;
171                                 field_pass.value = param.jelszo;
172                                 
173                                 var form = document.querySelector('form.loginForm');
174                                 form.submit();
175                                 
176                                 return 1;
177                         },
178                         function(param)
179                         {
180                                 var messageBox = document.querySelector('.messageBox');
181                                 var egyenleg_elem = document.querySelector('.szsz_egyenleg');
182                                 if(!egyenleg_elem && !messageBox)
183                                 {
184                                         console.log("Waiting for page to load...");
185                                         return 0;
186                                 }
187                                 if(messageBox)
188                                 {
189                                         console.log(messageBox.innerText);
190                                         return false;
191                                 }
192                                 var egyenleg = egyenleg_elem.innerText;
193                                 console.log("Egyenleg: " + egyenleg);
194                                 param.egyenleg = egyenleg;
195                                 return JSON.stringify({
196                                         jump: 1,
197                                         result: param,
198                                 });
199                         },
200                         function(param)
201                         {
202                                 var table = document.querySelector('form[name=korabbiMeroAllFormOnlineusz] table.rtable');
203                                 if(!table)
204                                 {
205                                         if(location.href == param.url_history)
206                                                 console.log("Waiting for page to load...");
207                                         else
208                                                 location.href = param.url_history;
209                                         return 0;
210                                 }
211                                 console.log(table.innerText);
212                                 if(param.show_history_only) return param.total_steps + 1;
213                                 return 1;
214                         },
215                         function(param)
216                         {
217                                 /* Navigate to 'Mérőállás bejelentés' page */
218                                 location.href = param.url_report;
219                                 return 1;
220                         },
221                         function(param)
222                         {
223                                 /* Wait for page to load */
224                                 var buttons = document.querySelectorAll('form#meroTajForm input.button');
225                                 if(!buttons)
226                                 {
227                                         console.log("Waiting for page "+location.href+" ...");
228                                         return 0;
229                                 }
230                                 for(var i = 0; i<buttons.length; i++)
231                                 {
232                                         console.log("[DEBUG] button \""+buttons[i].value+"\"");
233                                         if(buttons[i].value.match(/bejelent/))
234                                         {
235                                                 /* Submit form to proceed (1) */
236                                                 eval(param.clickFunc)(buttons[i]);
237                                                 return 1;
238                                         }
239                                 }
240                                 return 0;
241                         },
242                         function(param)
243                         {
244                                 /* Exit if we got an error page */
245                                 if(location.pathname.match(/meroHibalap/))
246                                 {
247                                         console.log(document.querySelector('form#meroHibalapForm').innerText);
248                                         return false;
249                                 }
250                                 /* Wait for page to load */
251                                 var buttons = document.querySelectorAll('input[type=submit][name^=meroallasBejelentes]');
252                                 if(!buttons)
253                                 {
254                                         console.log("Waiting for page "+location.href+" ...");
255                                         return 0;
256                                 }
257                                 
258                                 var inputs = document.querySelectorAll('form#meroallasBejelentes input.numberFormat');
259                                 for(var i = 0; i < inputs.length; i++)
260                                 {
261                                         console.log("Enter '"+param.oraallas[i]+"'");
262                                         inputs[i].value = param.oraallas[i];
263                                 }
264                                 
265                                 for(var i = 0; i<buttons.length; i++)
266                                 {
267                                         console.log("[DEBUG] button \""+buttons[i].value+"\"");
268                                         if(buttons[i].value.match(/mentés/))
269                                         {
270                                                 /* Submit form to proceed (2) */
271                                                 eval(param.clickFunc)(buttons[i]);
272                                                 return 1;
273                                         }
274                                 }
275                                 return 0;
276                         },
277                         function(param)
278                         {
279                                 var summary = document.querySelector('form#szamlaForm');
280                                 if(!summary)
281                                 {
282                                         console.log("Waiting for page "+location.href+" ...");
283                                         return 0;
284                                 }
285                                 console.log(summary.innerText);
286                                 
287                                 /* Accept Utility Bill */
288                                 var accept_btn = document.querySelector('input[name="szamlaForm:bOK"]');
289                                 eval(param.clickFunc)(accept_btn);
290                                 
291                                 return 1;
292                         },
293                         /*
294                                 FIXME
295                                 > ERROR: ReferenceError: Can't find variable: clickedButton
296                                 > STACK: [{"file":"https://www.nkmenergia.hu/aram/meroallas/meroSzamla.jsf?id=1300461","line":4648,"function":"onclick"},{"file":"","line":0,"function":"dispatchEvent"},{"file":"","line":1,"function":""},{"file":"","line":12,"function":""},{"file":"","line":15,"function":""}]
297                         */
298                         function(param)
299                         {
300                                 /* Wait for page to load */
301                                 var readyForm = document.querySelector('form#readyForm');
302                                 if(!readyForm)
303                                 {
304                                         console.log("Waiting for page "+location.href+" ...");
305                                         return 0;
306                                 }
307                                 /* Display Service Provider's message*/
308                                 console.log(readyForm.innerText);
309                                 return 1;
310                         }
311                 ];
312                 
313                 Glob.total_steps = steps.length;
314                 
315                 timeout = 500;
316                 worker = function()
317                 {
318                         if(!loadInProgress)
319                         {
320                                 /* Execute next step in navigator's context */
321                                 log(llDebug, "step " + stepindex);
322                                 var ret = page.evaluate(steps[stepindex], Glob);
323                                 
324                                 if(ret === false)
325                                 {
326                                         phantom.exit(1);
327                                 }
328                                 else if(ret === undefined || ret === null)
329                                 {
330                                         phantom.exit(4);
331                                 }
332                                 
333                                 if(typeof ret != "number")
334                                 {
335                                         ret = JSON.parse(ret);
336                                         for(var key in Glob)
337                                         {
338                                                 if(!ret.result.hasOwnProperty(key)) delete Glob[key];
339                                         }
340                                         for(var key in ret.result)
341                                         {
342                                                 Glob[key] = ret.result[key];
343                                         }
344                                         //stderr.write(JSON.stringify(Glob));
345                                         ret = ret.jump;
346                                 }
347                                 
348                                 log(llDebug, "step " + stepindex + " jump " + ret);
349                                 stepindex += ret;
350                                 
351                                 if(stepindex >= steps.length)
352                                 {
353                                         log(llDebug, "completed");
354                                         phantom.exit(0);
355                                 }
356                         }
357                         
358                         setTimeout(worker, timeout);
359                 }               
360                 setTimeout(worker, timeout);
361         }