Promises, Promises (Scraping Data with async functions)
I had to scrape a bunch of routing rules from a client’s default routing rules in Google Admin bc there’s no-way to export this list [accoridng to Google support]
Bad news: there’s no JSON api here to scrape/hack/curl
Worse news: Google’s CSRF policy is pretty damn hard to get around - so I had to write this little scrapper in vanilla JS with some promises to handle all the states
The biggest thing to note is that you have to prototype your own asyncForEach function when iterrating over an array, bc otherwise it’ll do them in any order it pleases
I needed each state to sucessfully execute and return before moving onto the next
find the correct element in the dom (this is tricky bc Google uses a virtual dom with their material UI, so good luck trying to use any type of class naming standard)
make sure that element is the one we want to simulate a click for (should have the text value of “edit” and an data-id attribute)
simulate click and wait for the modal to render
scrape the default routing rule for the internal address, map it to the external address in an array
constemails=[];Array.prototype.asyncForEach=asyncfunction(callback,thisArg){thisArg=thisArg||thisfor(leti=0,l=this.length;i!==l;++i){awaitcallback.call(thisArg,this[i],i,this)}}functionwait(){returnnewPromise(function(resolve,reject){setTimeout(function(){console.log('waiting 1 sec')resolve();},1000);})}functionclickElement(el){returnnewPromise((resolve,reject)=>{console.log('emulating click for ',el)el.click();resolve();})}functiongetEmails(el){returnnewPromise((resolve,reject)=>{console.log('getting emails for ',el)varsearch_in=document.activeElement.innerHTML;string_context=search_in.toString();array_mails=string_context.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);letuniques=Array.from(newSet(array_mails));emails.push(uniques);resolve();})}functioncloseModal(){returnnewPromise((resolve,reject)=>{constlinks=Array.from(document.activeElement.querySelectorAll('span'));for(leti=0;i<links.length;i++){if(links[i].textContent==='Cancel'){console.log('closing top window')links[i].click();resolve();break;}}})}asyncfunctionscrapePage(){varelements=document.querySelectorAll('td a:first-child');awaitArray.prototype.asyncForEach.call(elements,asyncfunction(el,i){if((el.innerHTML.indexOf("Edit")!=-1)&&(el.hasAttribute("data-id"))){awaitclickElement(el);awaitwait();awaitgetEmails(el);awaitwait();awaitcloseModal();awaitwait();}});}scrapePage();