// ==UserScript== // @name Direct download from Google Play // @namespace StephenP // @version 2.8.1 // @description Adds APK-DL, APKPure, APKCombo, APKMirror and Evozi download buttons to Google Play when browsing apps. This script is based on yurenchen's "google play apk downloader". // @author StephenP // @icon https://play.google.com/favicon.ico // @match https://play.google.com/* // @match http://play.google.com/* // @match http://apkfind.com/store/captcha?app=* // @grant GM.xmlHttpRequest // @grant GM.download // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js // @connect self // @connect apkpure.com // @connect apkfind.com // @connect apk-cloud.com // @connect winudf.com // @connect apkcombo.com // @connect gpudf.down-apk.com // @connect play.googleapis.com // @connect gvt1.com // @downloadURL none // ==/UserScript== var ui; var wlButton; var pageURL; var title; var appCwiz; var done=[0]; var useGS=false; (function() { if(document.location.href.includes("apkfind")===true){ setInterval(unredirect,100); } else{ try{ 'use strict'; var site=window.location.href.toString(); ui=checkUI(); pageURL=location.href; if(ui>0){ title=document.getElementById("main-title").innerHTML; } if(ui>=3){ var buttonsStyle=document.createElement("style"); var styleString='.ddlButton:visited{color: white;} .ddlButton:hover{opacity: 0.8;} .ddlButton:active{opacity: 0.6;} .ddlButton{color: white; border-radius: 4px; border: 1px; font-size: 14px; height: 46px; padding: 9px 20px; font-weight: 500; font-family: "Roboto",sans-serif; position: relative; text-align: center; line-height: 46px;'; if(ui==3){ styleString+=' margin-right: 4px;}'; buttonsStyle.innerHTML=styleString; } if(ui==4){ styleString+=' margin-left: 4px;}'; buttonsStyle.innerHTML=styleString; } document.body.appendChild(buttonsStyle); } if(pageURL.includes("details?id=")){ addButtons(); } setInterval(checkReload, 2000); } catch(err){ console.log("main(): "+err); } } })(); function unredirect(){ var tot=document.body.children.length-1; if(parseInt(document.body.children[tot].style.zIndex, 10)>2){ if(document.body.children[tot].id==""){ document.body.children[tot].style.zIndex="1"; document.body.children[tot-1].style.zIndex="-1000"; } else{ document.body.children[tot].style.zIndex="-1000"; } } } function waitForRemovingButtons(){ //if(title!=document.getElementById("main-title").innerHTML){ if((pageURL!=location.href)||(isButtonVisible()===false)){ title=document.getElementById("main-title").innerHTML; pageURL=location.href; wlButton=null; if(location.href.includes("details?id=")){ if((ui>=3)&&(document.getElementsByClassName("ddlButton").length>0)){ try{ removePreviousCwiz(); } catch(err){ console.log(err+"; I was probably just trying to remove buttons that weren't there..."); } } addButtons(); } } else{ setTimeout(waitForRemovingButtons, 1000); } } function checkReload(){ if((pageURL!=location.href)||(isButtonVisible()===false)){ waitForRemovingButtons(); } } function isButtonVisible(){ var allButtons=document.getElementsByClassName("ddlButton"); //console.log("how many buttons: "+allButtons.length); if(allButtons.length>0){ for(var i=0;i0)){ installButton=document.getElementsByClassName("buy")[0]; try{ price=installButton.firstElementChild.firstElementChild.getElementsByTagName("META")[1].content; //alert("Price: "+price); } catch(err){ console.error("Price not found. Maybe the app is already installed?"); price=0; } } else if(ui>2){ instWishButtons=getUglyUIButtons(); if(ui==3){ installButton=instWishButtons[0]; } else{ installButton=instWishButtons[1]; //if the app is installed, the whishlist button is absent, so the install button is the first and only if(typeof installButton==='undefined'){ installButton=instWishButtons[0]; } } do{ installButton=installButton.parentNode; }while(installButton.tagName!="C-WIZ"); try{ price=installButton.firstElementChild.firstElementChild.getElementsByTagName("META")[1].content; //alert("Price: "+price); } catch(err){ console.error("Price not found. Maybe the app is already installed?"); price=0; } //determina c-wiz dell'app per poterlo radere al suolo al cambio di pagina var currentNode; currentNode=installButton.parentNode; do{ if(currentNode.tagName=="C-WIZ"){ appCwiz=currentNode; } currentNode=currentNode.parentNode; }while(currentNode.tagName!="BODY"); } else{ document.getElementById("search-section").lastChild.remove(); document.getElementById("search-section").innerHTML+='or search on APKMirror
'; } if(price==0){ var html; var buttonslist; var id=location.search.match(/id=(.*)/)[1].split("&", 1); var apkpureURL='https://m.apkpure.com/genericApp/'+id+'/download'; var evoziURL='https://apps.evozi.com/apk-downloader/?id='+id; var apkdlURL='http://apkfind.com/store/download?id='+id; var apkmirrorURL='https://www.apkmirror.com/?post_type=app_release&searchtype=apk&s='+id; var apkleecherURL='https://apkleecher.com/download/dl.php?dl='+id; var apkcomboURL='https://apkcombo.com/genericApp/'+id+'/download/apk'; wlButton = document.createDocumentFragment(); var wishListButton; if(ui<=2){ wishListButton=document.getElementsByClassName("id-wishlist-display")[0]; } else{ if(typeof instWishButtons[1]!=='undefined'){ wishListButton=instWishButtons[0]; do{ wishListButton=wishListButton.parentNode; }while(wishListButton.tagName!="C-WIZ"); } } if(ui==1){ buttonslist = document.getElementsByClassName("details-actions")[0]; html='APK‑DLAPKPureAPKCombo
EvoziAPKMirror
Use Google\'s servers when downloading from APKCombo'; } else if(ui==2){ buttonslist = document.getElementsByClassName("details-actions-right")[0]; html='APK‑DLAPKPureAPKCombo
EvoziAPKMirror
Use Google\'s servers when downloading from APKCombo'; } else{ buttonslist = installButton.parentNode; html='APK‑DLAPKPureAPKCombo
EvoziAPKMirror
Use Google\'s servers when downloading from APKCombo'; } if(ui<=2){ wlButton.appendChild(wishListButton); } else{ if(typeof wishListButton!=='undefined'){ wlButton.appendChild(wishListButton.firstChild.firstChild); } } buttonslist.innerHTML=buttonslist.innerHTML+html; buttonslist.appendChild(wlButton); var ddlButton1=document.getElementById("apkdlbutton"); ddlButton1.onclick=function(){ddl(this,apkdlURL);}; var ddlButton2=document.getElementById("apkpurebutton"); ddlButton2.onclick=function(){ddl(this,apkpureURL);}; var ddlButton3=document.getElementById("apkcombobutton"); ddlButton3.onclick=function(){ddl(this,apkcomboURL);}; document.getElementById("useGoogleServers").checked=useGS; } } function openLink(link){ window.open(link.replace("http://","https://"),"_self"); } function ddlFinalApk(link,ddlButton,i){ if(link!=""){ done[i]=0; GM.xmlHttpRequest({ method: "GET", url: link, timeout: 5000, ontimeout: function(response) { if(done[i]==0){ ddlButton.firstChild.innerHTML="Retry"; } else{ done[i]=0; } }, onprogress: function(response){ //console.log(response.finalUrl); if((response.finalUrl.includes("winudf.com"))||(response.finalUrl.includes("down-apk.com"))||(response.finalUrl.includes("/play-apps-download-default/"))){ if(done[i]==0){ console.log("downloading file n."+i); done[i]=1; if(link.includes("apkpure")){ window.open(response.finalUrl,"_self"); ddlButton.onclick=function(){openLink(response.finalUrl);}; ddlButton.firstChild.innerHTML="Ready!"; } else{ window.open(response.finalUrl,i); ddlButton.firstChild.innerHTML="APKCombo"; } } } }, onload: function(response){ if(done[i]==0){ ddlButton.firstChild.innerHTML="Retry"; } else{ done[i]=0; } }, onerror: function(){ buttonError(ddlButton,"Offline!"); } }); } else{ buttonError(ddlButton,"Failed!"); } } function ddl(ddlButton,ddlURL){ ddlButton.firstChild.innerHTML="Loading..."; if(ddlURL.includes("apkfind")){ try { var apkDlRequest1=GM.xmlHttpRequest({ method: "GET", url: ddlURL, onload: function(response) { if(response.finalUrl.includes("/captcha?")){ ddlButton.firstChild.setAttribute("href",response.finalUrl); ddlButton.firstChild.innerHTML="CAPTCHA"; ddlButton.onclick=null; } else if(response.finalUrl.includes("app/removed")){ buttonError(ddlButton,"Removed!"); } else{ try{ var linkIntermediary = document.createElement("html"); linkIntermediary.innerHTML=response.response; var link="http:"+linkIntermediary.getElementsByClassName("mdl-button")[0].getAttribute("href"); ddlButton.firstChild.innerHTML="Ready!"; openLink(link); ddlButton.onclick=function(){openLink(link);}; } catch(err){ buttonError(ddlButton,"Failed!"); console.log(err); } } }, onerror: function(){ buttonError(ddlButton,"Offline!"); } }); } catch (err) { buttonError(ddlButton,"Failed!"); console.log(err); } } else if(ddlURL.includes("apkpure")){ try{ GM.xmlHttpRequest({ method: "GET", url: ddlURL, onload: function(response) { switch (response.status) { case 410: buttonError(ddlButton, "Removed!"); break; case 404: buttonError(ddlButton, "Not found!"); break; default: var apklink=response.responseText.substr(response.responseText.indexOf('https://download.apkpure.com/b/'),response.responseText.length-1); apklink=apklink.substr(0,apklink.indexOf('"')); console.log(ddlURL); ddlButton.firstChild.innerHTML="Wait..."; //ddlButton.onclick=function(){GM.openInTab(apklink,"open_in_background");}; ddlFinalApk(apklink,ddlButton,0); } }, onerror: function(){ buttonError(ddlButton,"Offline!"); } }); } catch(err){ buttonError(ddlButton,"Failed!"); console.log(err); } } else if(ddlURL.includes("apkcombo")){ try{ GM.xmlHttpRequest({ method: "GET", url: ddlURL, onload: function(response) { switch (response.status) { case 410: buttonError(ddlButton, "Removed!"); break; case 404: buttonError(ddlButton, "Not found!"); break; default: try { var i; var parser = new DOMParser(); var resp = parser.parseFromString(response.responseText, 'text/html'); var google = resp.getElementById("origin-server-tab"); var combo = resp.getElementById("apkcombo-server-tab"); var useGoogleServers=document.getElementById("useGoogleServers").checked; setUseGS(useGoogleServers); if ((google !== null)&&((combo === null)||(useGoogleServers==true))) { var googlelinks = google.getElementsByTagName("a"); for (i = 0; i < googlelinks.length; i++) { ddlFinalApk(googlelinks[i].getAttribute("href"), ddlButton, i); } } else if ((combo !== null)&&(useGoogleServers==false)) { var combolinks = combo.getElementsByTagName("a"); for (i = 0; i < combolinks.length; i++) { ddlFinalApk(combolinks[i].getAttribute("href"), ddlButton, i); } } else{ //if loading the main download page results in an empty list of apks, tries to read the token to request directly the urls from apkcombo server var tokenStart=response.responseText.indexOf("/dl?token=")+4; var tokenEnd=response.responseText.indexOf("\"",tokenStart); var token = response.responseText.substring(tokenStart,tokenEnd); ddlURL=response.finalUrl; GM.xmlHttpRequest({ method: "POST", url: ddlURL.replace("/download/apk", "/dl")+"?"+token, onload: function(response) { var parser2 = new DOMParser(); var resp2 = parser2.parseFromString(response.responseText, 'text/html'); google = resp2.getElementById("origin-server-tab"); combo = resp2.getElementById("apkcombo-server-tab"); if ((google !== null)&&((combo === null)||(useGoogleServers==true))) {//same as above var googlelinks = google.getElementsByTagName("a"); for (i = 0; i < googlelinks.length; i++) { ddlFinalApk(googlelinks[i].getAttribute("href"), ddlButton, i); } } else if ((combo !== null)&&(useGoogleServers==false)) { var combolinks = combo.getElementsByTagName("a"); for (i = 0; i < combolinks.length; i++) { ddlFinalApk(combolinks[i].getAttribute("href"), ddlButton, i); } } else { ddlButton.firstChild.setAttribute("href", ddlURL); ddlButton.firstChild.innerHTML = "New tab >"; ddlButton.onclick = null; } }, onerror: function(response) { buttonError(ddlButton, "Error!"); } }); } } catch (err) { console.log(err); } } }, onerror: function(){ buttonError(ddlButton,"Offline!"); } }); } catch(err){ buttonError(ddlButton,"Failed!"); console.log(err); } } } function getUglyUIButtons() { var matchingElements=[]; var allElements = document.getElementsByTagName('button'); for (var i = 0, n = allElements.length; i < n; i++) { if (allElements[i].getAttribute("data-item-id")!==null) { if (allElements[i].getAttribute("data-item-id").startsWith("%.@.")===true){ matchingElements.push(allElements[i]); } } } //alert(matchingElements.length); shows how many buttons for installation and whishlist are in the page return matchingElements; } function checkUI(){ //Different UIs: //1=Mobile HTML //2=Desktop HTML //3=Mobile UglyUI //4=Desktop UglyUI var check=0; try{ if(document.getElementsByClassName("action-bar-menu-button").length>0){ check=1; } else{ if(document.getElementsByClassName("details-info").length>0){ check=2; } else if(!document.getElementById("error-section")){ check=4; var metaTags=document.head.getElementsByTagName("meta"); for(var i=0;i