summaryrefslogtreecommitdiff
path: root/post_fsd_wiki.phantomjs
blob: 7c18925174d6568576f4c0e6113c05718aeb2dda (plain)
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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
var BLACKLIST_DATA_FILE   = './blacklist-testdata.json' ;
var WIKI_TEMPLATE_FILE    = './wiki-template.json' ;
var WIKI_BASE_URL         = 'http://localhost/mediawiki/index.php' ;
// var WIKI_BASE_URL  = 'https://directory.fsf.org/wiki?title=' ;
var LOGIN_URL             = WIKI_BASE_URL + '?title=Special:UserLogin' ;
var EDIT_URL              = WIKI_BASE_URL + '?title=_TITLE_&action=edit' ;
var USAGE_MSG             = "USAGE: phantomjs ./post_fsd_wiki.phantomjs <WIKI_LOGIN> <WIKI_PASS>" ;
var TITLE_URL_REGEX       = /_TITLE_/ ;
var PARABOLA_ENTRY_HEADER = '== Parabola Blacklist Description ==\n' ;
var WIKI_TEXT_BEGIN       = '<!-- PARABOLA BLACKLIST BEGIN (DO NOT EDIT) -->' + PARABOLA_ENTRY_HEADER ;
var WIKI_TEXT_END         = '\n<!-- PARABOLA BLACKLIST END -->\n' ;
var WIKI_TEXT_REGEX       = RegExp(WIKI_TEXT_BEGIN.replace(/\((.*)\)/ , '\\($1\\)') + '.*' + WIKI_TEXT_END) ;
var LOGIN_IMPUT_ID        = 'wpName1' ;
var PASS_IMPUT_ID         = 'wpPassword1' ;
var LOGIN_SUBMIT_IMPUT_ID = 'wpLoginAttempt' ;
var USERNAME_LI_ID        = 'pt-userpage' ;
var EDIT_TEXT_INPUT_ID    = 'wpTextbox1' ;
var EDIT_SUBMIT_INPUT_ID  = 'wpSave' ;
var WIKI_TITLE_H1_ID      = 'firstHeading' ;
var WIKI_TEXT_DIV_ID      = 'mw-content-text' ;
var PACKAGE_NAME_KEY      = 'original_package' ;  // BLACKLIST_DATA_FILE JSON per ./SYNTAX CSV[0]
var REPLACEMENT_KEY       = 'libre_replacement' ; // BLACKLIST_DATA_FILE JSON per ./SYNTAX CSV[1]
var REFERENCE_KEY         = 'ref' ;               // BLACKLIST_DATA_FILE JSON per ./SYNTAX CSV[2]
var ENTRY_ID_KEY          = 'id' ;                // BLACKLIST_DATA_FILE JSON per ./SYNTAX CSV[3]
var DESCRIPTION_KEY       = 'short_description' ; // BLACKLIST_DATA_FILE JSON per ./SYNTAX CSV[4]
var BLACKLIST_TAGS_KEY    = 'blacklist_tags'      // BLACKLIST_DATA_FILE JSON
var STEP_FUNCTION_KEY     = 'step-function' ;
var PAGELOAD_WAIT_KEY     = 'wait-for-pageload' ;
var STEP_TIMEOUT          = 3000 ; var StepTimeout ;

var System     = require('system') ;
var Args       = System.args ;
var Page       = require('webpage').create() ;
var WIKI_LOGIN = Args[1] || '' ;
var WIKI_PASS  = Args[2] || '' ;
var WikiPages  = [] ; var WikiPage ;
var Steps      = [] ; var Step ;
var StepN      = 0 ;
var IsReady    = true ;
var ShouldWait = false ;
var ShouldQuit = false ;


if (WIKI_LOGIN == '' || WIKI_PASS == '') { LOG(USAGE_MSG) ; phantom.exit() ; } LOG('') ;


/* steps */

function Prepare()
{
  LOG("loading BLACKLIST_DATA_FILE") ; var blacklist_data = require(BLACKLIST_DATA_FILE) ;

  if (!IsA(blacklist_data , Array )) { ForceQuit("failed to load package data") ;  return ; }

  LOG("found " + blacklist_data.length + " packages") ;

  blacklist_data.forEach(function(package_data)
  {
    var page_title = package_data[PACKAGE_NAME_KEY].trim() ;
    var page_text  = package_data[DESCRIPTION_KEY ].trim() ;

    if (!page_title || !IsA(page_title , String) ||
        !page_text  || !IsA(page_text  , String)  )
    { ForceQuit("invalid package data: " + JSON.stringify(package_data)) ; return ; }

    LOG("found package: " + page_title) ;

    var wiki_page               = {} ;
    wiki_page[PACKAGE_NAME_KEY] = page_title.toLowerCase().replace(/ /g , '_') ;
    wiki_page[DESCRIPTION_KEY ] = page_text ;
    WikiPages.push(wiki_page) ;
  }) ;

  IsReady = true ;
}

function LoadLoginPage()
{
  if (WikiPages.length == 0) { ForceQuit("no WikiPages to consider") ; return ; }

  for (page_n in WikiPages)
  {
    var wiki_page_data = WikiPages[page_n] ;
    var page_title     = wiki_page_data[PACKAGE_NAME_KEY] ;
    var page_text      = wiki_page_data[DESCRIPTION_KEY ] ;

    if (!page_title || !IsA(page_title , String)) { ForceQuit("invalid wiki page data") ; return ; }
    if (!page_text  || !IsA(page_text  , String)) { ForceQuit("invalid wiki page data") ; return ; }

    LOG("loaded package data: " + page_title) ;
  }

  GetUrl(LOGIN_URL) ;
}

function SubmitLogin()
{
  EvalQuitOnErr(Page.evaluate(function(login_input_id , pass_input_id , submit_input_id ,
                                   wiki_login     , wiki_pass                       )
  {
    var login_input   = document.getElementById(login_input_id ) ;
    var pass_input    = document.getElementById(pass_input_id  ) ;
    var submit_button = document.getElementById(submit_input_id) ;
    var login_form    = submit_button.form ;

    if (!login_input   || login_input.nodeName   != 'INPUT'  ||
        !pass_input    || pass_input.nodeName    != 'INPUT'  ||
        !submit_button || submit_button.nodeName != 'BUTTON' ||
        !login_form    || login_form.nodeName    != 'FORM'    )
      return "ERROR: invalid login page" ;

    login_input.value = wiki_login ;
    pass_input.value  = wiki_pass ;

    login_form.submit() ;

  } , LOGIN_IMPUT_ID , PASS_IMPUT_ID , LOGIN_SUBMIT_IMPUT_ID , WIKI_LOGIN , WIKI_PASS)) ;
}

function VerifyLogin()
{
  EvalQuitOnErr(Page.evaluate(function(username_li_id , wiki_login)
  {
    var username_li = document.getElementById(username_li_id) ;
    var username    = !!username_li && username_li.textContent.toLowerCase() ;

    if (!username_li || username_li.nodeName != 'LI' ||
        username != wiki_login.toLowerCase()          )
      return "ERROR: login failed" ;

    console.info("signed in as: " + username) ;
  } , USERNAME_LI_ID , WIKI_LOGIN)) ;
}

function LoadWikiData()
{
  LOG(WikiPages.length + " remaining") ;

  if (!!(WikiPage = WikiPages.shift())) IsReady = true ; else Done() ;
}

function LoadEditPage()
{
  var page_title = WikiPage[PACKAGE_NAME_KEY] ;

  GetUrl(EditPageUrl(page_title)) ;
}

function SubmitEdit()
{
if (DEBUG) DBG("in") ;

  var page_title = WikiPage[PACKAGE_NAME_KEY] ;
  var wiki_text  = WikiPage[DESCRIPTION_KEY ] ;

  if (Page.url != EditPageUrl(page_title)) { ForceQuit("edit page load failed") ; return ; }

  var post_wiki_text = EvalQuitOnErr(Page.evaluate(function(wiki_text_input_id , wiki_submit_button_id ,
                                                            wiki_text_regex    , new_wiki_text         )
  {
    var wiki_text_input    = document.getElementById(wiki_text_input_id   ) ;
    var wiki_submit_button = document.getElementById(wiki_submit_button_id) ;
    var existing_wiki_text = !!wiki_text_input && wiki_text_input.value ;

// console.log("submitEdit() wiki_text_input=" + wiki_text_input   ) ;
// console.log("submitEdit() wiki_text_input   .nodeName" + wiki_text_input   .nodeName) ;
// console.log("submitEdit() wiki_submit_button" + wiki_submit_button) ;
// console.log("submitEdit() wiki_submit_button.nodeName" + wiki_submit_button.nodeName) ;

    if (!wiki_text_input    || wiki_text_input   .nodeName != 'TEXTAREA' ||
        !wiki_submit_button || wiki_submit_button.nodeName != 'INPUT'     )
      return "ERROR: invalid edit page" ;

    var modified_wiki_text = existing_wiki_text.replace(wiki_text_regex , new_wiki_text) ;
    var concat_wiki_text   = existing_wiki_text + new_wiki_text ;
    var post_wiki_text     = (!wiki_text_regex.test(existing_wiki_text)) ? concat_wiki_text   :
                             (modified_wiki_text != existing_wiki_text ) ? modified_wiki_text : '' ;

// console.log("submitEdit() new_wiki_text=" + new_wiki_text) ;
// console.log("submitEdit() existing_wiki_text=" + existing_wiki_text) ;
// console.log("submitEdit() modified_wiki_text=" + modified_wiki_text) ;
// console.log("submitEdit() (modified_wiki_text == existing_wiki_text)=" + (modified_wiki_text == existing_wiki_text)) ;
// console.log("submitEdit() wiki_text_regex.test(existing_wiki_text)=" + wiki_text_regex.test(existing_wiki_text)) ;
// console.log("submitEdit() post_wiki_text=" + post_wiki_text) ;

    if (!!post_wiki_text) { wiki_text_input.value = post_wiki_text ; wiki_submit_button .click() ; }

    return post_wiki_text ;

  } , EDIT_TEXT_INPUT_ID , EDIT_SUBMIT_INPUT_ID                       ,
      WIKI_TEXT_REGEX    , WIKI_TEXT_BEGIN + wiki_text + WIKI_TEXT_END)) ;

// DBG("returned post_wiki_text=" + post_wiki_text) ;

  if (!post_wiki_text) { LOG("wiki text has not changed - skipping") ; NextPage() ; return ; }

/*
console.log("edit_form.action=" + edit_form.action) ;
var edit_form_fields = edit_form.getElementsByTagName('input') ;
for (child_node_n in edit_form_fields)
{
  if (!edit_form.hasOwnProperty(child_node_n)) continue ;

  var child_node  = edit_form_fields[child_node_n] ;
  var field_key   = child_node.name ;
  var field_value = child_node.value ;

  if (child_node.type != 'hidden' || !field_key || !field_value) continue ;

// field_key=wpStarttime field_value=20180121060903
// field_key=wpEdittime field_value=20180121060903
// field_key=wpAutoSummary field_value=d41d8cd98f00b204e9800998ecf8427e
// field_key=oldid field_value=0
// field_key=parentRevId field_value=0
// field_key=format field_value=text/x-wiki
// field_key=model field_value=wikitext
// field_key='wpEditToken field_value=d70645952b36fc2f29c73a665bb3acf45a642e80+\'
// field_key=wpUltimateParam field_value=1
console.log("child_node=" + child_node + " field_key=" + field_key + " field_value=" + field_value) ;
}
*/
/*
    var xhr = new XMLHttpRequest() ;
var url = edit_form.action ;
    var params = "lorem=ipsum&name=binny" ;
    xhr.open('POST' , url , true) ;
    xhr.setRequestHeader('Content-type' , 'application/x-www-form-urlencoded') ;

    xhr.onreadystatechange = function()
    {
      if (xhr.readyState == 4 && xhr.status == 200)
      {
console.log(xhr.responseText) ;
      }
    }) ;
    xhr.send(params) ;
*/
/*
  var post_body = 'wpTextbox1=' + post_wiki_text +
                  '&wpSave=' + 'Save page' +
                  '&wpEditToken=' + edit_token ;
  PostUrl(edit_form_action , post_body) ;
*/
if (DEBUG) DBG("out") ;
}

function VerifyEdit()
{
if (DEBUG) DBG("in") ;

  var page_title   = WikiPage[PACKAGE_NAME_KEY] ;
  var wiki_text    = WikiPage[DESCRIPTION_KEY ] ;
  var expected_url = WIKI_BASE_URL + '/' + page_title ;
  page_title       = page_title.replace(/_/g , ' ') ;
  wiki_text        = PARABOLA_ENTRY_HEADER.replace(/=/g , '').trim() + '\n' + wiki_text ;

// DBG("Page.url=" + Page.url.toLowerCase()) ; DUMPFILE(Page.content) ;

  if (Page.url.toLowerCase() != expected_url) { ForceQuit("edit post failed") ; return ; }

  var err = EvalQuitOnErr(Page.evaluate(function(wiki_title_h1_id , wiki_text_div_id ,
                                                 page_title       , new_wiki_text    )
  {
    var wiki_title_h1       = document.getElementById(wiki_title_h1_id) ;
    var wiki_text_div       = document.getElementById(wiki_text_div_id) ;
    var existing_wiki_title = !!wiki_title_h1 && wiki_title_h1.textContent.toLowerCase() ;
    var existing_wiki_text  = !!wiki_text_div && wiki_text_div.textContent.trim() ;
    var wiki_text_regex     = RegExp(new_wiki_text) ;

console.log("wiki_title_h1=" + wiki_title_h1 + " wiki_title_h1.nodeName=" + wiki_title_h1.nodeName) ;
console.log("wiki_text_div=" + wiki_text_div + " wiki_text_div.nodeName=" + wiki_text_div.nodeName) ;
console.log("existing_wiki_title=" + existing_wiki_title) ;
console.log("page_title=" + page_title) ;
console.log("existing_wiki_text=" + existing_wiki_text) ;
console.log("new_wiki_text=" + new_wiki_text) ;
console.log("(existing_wiki_title == page_title    )=" + (existing_wiki_title == page_title)) ;
console.log("wiki_text_regex.test(existing_wiki_text)=" + wiki_text_regex.test(existing_wiki_text)) ;

    if (!wiki_title_h1 || wiki_title_h1.nodeName != 'H1'  || existing_wiki_title != page_title       ||
        !wiki_text_div || wiki_text_div.nodeName != 'DIV' || !wiki_text_regex.test(existing_wiki_text))
      return "ERROR: edit post failed" ;

  } , WIKI_TITLE_H1_ID , WIKI_TEXT_DIV_ID , page_title , wiki_text)) ;

  if (!err) LOG("successfully updated: " + page_title) ; NextPage() ;
}


/* main loop */

function DefineStep(step_function , should_wait_for_pageload)
{
  var step_data                = {} ;
  step_data[STEP_FUNCTION_KEY] = step_function ;
  step_data[PAGELOAD_WAIT_KEY] = should_wait_for_pageload ;
  Steps.push(step_data) ;
}


function MainLoop()
{
if (DEBUG_VB) DBG("ShouldQuit=" + ShouldQuit + " IsReady=" + IsReady) ;

  if      (!!ShouldQuit) { ERR(ShouldQuit) ; Done() ; return ; }
  else if (!IsReady    ) { PumpMainLoop() ;           return ; }

  clearTimeout(StepTimeout) ;

  StepTimeout   = setTimeout(function() { ForceQuit("timeout executing step") ; } , STEP_TIMEOUT) ;
  var step_data = Steps[StepN++] ;
  var step      = step_data && step_data[STEP_FUNCTION_KEY] ;
  ShouldWait    = step_data && step_data[PAGELOAD_WAIT_KEY] ;
  IsReady       = false ;

  if (typeof step !== 'function') Done() ;
  else                            { LOG_STEP(step.name) ; step() ; PumpMainLoop() ; }
}

function PumpMainLoop() { setTimeout(MainLoop , 250) ; }

function ForceQuit(quit_msg) { ShouldQuit = quit_msg ; PumpMainLoop() ; }

function Done() { LOG("done") ; phantom.exit() ; LOG('') ; }


/* helpers */

function GetUrl(get_url)
{
DBG("get_url=" + get_url) ;

  Page.open(get_url , function(status) { if (status != 'success') ForceQuit("status: " + status) ; }) ;
}

function PostUrl(post_url , post_body)
{
DBG("post_url=" + post_url) ;

  Page.open(post_url , 'POST' , post_body , function(status)
  {
    if (status != 'success') ForceQuit("status: " + status) ;
  }) ;
}

function EvalQuitOnErr(result)
{
  if (typeof result == 'string' && !result.indexOf('ERROR:')) ForceQuit(result) ;
  else                                                        IsReady = !ShouldWait ;

  return result ;
}

function NextPage() { StepN = NEXT_PAGE_STEP ; IsReady = true ; }

function IsA(an_object , expected_type)
{
  switch(expected_type)
  {
    case Array:  expected_type = '[object Array]' ;  break ;
    case String: expected_type = '[object String]' ; break ;
  }

  return (Object.prototype.toString.call(an_object) === expected_type) ;
}

function EditPageUrl(page_title) { return EDIT_URL.replace(TITLE_URL_REGEX , page_title) ; }


/* event hendlers */

Page.onLoadStarted  = function() { IsReady = false ; ARGS.apply("Page.onLoadStarted" , arguments) ;              } ;

Page.onLoadFinished = function() { IsReady = true ;  ARGS.apply("Page.onLoadFinished " + Page.url , arguments) ; } ;

Page.onUrlChanged   = function() {                   ARGS.apply("Page.onUrlChanged"  , arguments) ;              } ;


/* logging */

Page.onConsoleMessage = function(msg) { LOG(msg) ; } ;

var DEBUG = false ; var DEBUG_EVS = DEBUG && false ; var DEBUG_VB = DEBUG && false ;
function LOG     (log , color) { console.log((color || '\033[00;32m') + log  + '\033[00m'   ) ;    }
function LOG_STEP(name)        { LOG("Step: "                         + name , '\033[01;32m') ;    }
function ERR     (err)         { LOG("ERROR: "                        + err  , '\033[00;31m') ;    }
function DBG     (dbg)         { if (!DEBUG) return ;
                                 dbg = ((!!DBG.caller.name) ? DBG.caller.name + "() " : '') + dbg ;
                                 LOG("DEBUG: "                        + dbg  , '\033[00;34m') ;    }
function ARGS    ()            { if (!DEBUG_EVS) return ;
                                 LOG("EVENT: " + this) ; var args = arguments ;
                                 for (arg in args) LOG("  arg: " + JSON.stringify(args[arg])) ;      }
function DUMPFILE(content) { require('fs').write('dump.txt' , content , 'w') ; }


/* main entry */

DefineStep(Prepare       , false) ;
DefineStep(LoadLoginPage , true ) ;
DefineStep(SubmitLogin   , true ) ;
DefineStep(VerifyLogin   , false) ;
DefineStep(LoadWikiData  , false) ;
DefineStep(LoadEditPage  , true ) ;
DefineStep(SubmitEdit    , true ) ;
DefineStep(VerifyEdit    , false) ;
for (step_n in Steps) if (Steps[step_n][STEP_FUNCTION_KEY].name == 'LoadWikiData') NEXT_PAGE_STEP = step_n ;

MainLoop() ;