Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
55ba024
commit c3cca69
Showing
2 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#!/usr/bin/env python | ||
|
||
__author__ = 'TripCode' | ||
__copyright__ = 'Copyright (C) 2016' | ||
__license__ = 'GPLv3' | ||
__product__ = 'WhatsAppGDExtract' | ||
__version__ = 1.0 | ||
__website__ = 'https://github.com/EliteAndroidApps' | ||
|
||
import ConfigParser | ||
import json | ||
import os | ||
import re | ||
import requests | ||
import sys | ||
|
||
def getGoogleAccountTokenFromAuth(): | ||
payload = {'Email':gmail,'Passwd':passw,'app':client_pkg,'client_sig':client_sig,'parentAndroidId':devid} | ||
request = requests.post('https://android.clients.google.com/auth',data=payload) | ||
token = re.search('Token=(.*?)\n',request.text) | ||
if token: | ||
return token.group(1) | ||
else: | ||
quit(request.text) | ||
|
||
def getGoogleDriveToken(token): | ||
payload = {'Token':token,'app':pkg,'client_sig':sig,'device':devid,'google_play_services_version':client_ver,'service':'oauth2:https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file','has_permission':'1'} | ||
request = requests.post('https://android.clients.google.com/auth',data=payload) | ||
token = re.search('Auth=(.*?)\n',request.text) | ||
if token: | ||
return token.group(1) | ||
else: | ||
quit(request.text) | ||
|
||
def rawGoogleDriveRequest(bearer,url): | ||
headers = {'Authorization': 'Bearer '+bearer} | ||
request = requests.get(url,headers=headers) | ||
return request.text | ||
|
||
def downloadFileGoogleDrive(bearer,url,local): | ||
if not os.path.exists(os.path.dirname(local)): | ||
os.makedirs(os.path.dirname(local)) | ||
if os.path.isfile(local): | ||
os.remove(local) | ||
headers = {'Authorization': 'Bearer '+bearer} | ||
request = requests.get(url,headers=headers,stream=True) | ||
request.raw.decode_content = True | ||
if request.status_code == 200: | ||
with open(local, 'wb') as asset: | ||
for chunk in request.iter_content(1024): | ||
asset.write(chunk) | ||
print 'Downloaded: "'+local+'".' | ||
|
||
def getWhatsAppAuthBearer(token): | ||
return getGoogleDriveToken(token) | ||
|
||
def gDriveFileMap(): | ||
global bearer | ||
data = rawGoogleDriveRequest(bearer,'https://www.googleapis.com/drive/v2/files') | ||
jres = json.loads(data) | ||
for i in range(0,10): | ||
try: | ||
if jres['items'][i]['title'] == 'gdrive_file_map': | ||
n = i | ||
except: | ||
pass | ||
try: | ||
n | ||
except UnboundLocalError: | ||
quit('Unable to locate google drive file map for: '+pkg+'.') | ||
return jres['items'][n]['description'],rawGoogleDriveRequest(bearer,jres['items'][n]['downloadUrl']) | ||
|
||
def getConfigs(): | ||
global gmail, passw, devid, pkg, sig, client_pkg, client_sig, client_ver | ||
config = ConfigParser.RawConfigParser() | ||
try: | ||
config.read('settings.cfg') | ||
gmail = config.get('auth','gmail') | ||
passw = config.get('auth','passw') | ||
devid = config.get('auth','devid') | ||
pkg = config.get('app','pkg') | ||
sig = config.get('app','sig') | ||
client_pkg = config.get('client','pkg') | ||
client_sig = config.get('client','sig') | ||
client_ver = config.get('client','ver') | ||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): | ||
quit('The "settings.cfg" file is missing or corrupt!') | ||
|
||
def jsonPrint(data): | ||
print json.dumps(json.loads(data), indent=4, sort_keys=True) | ||
|
||
def localFileLog(md5): | ||
logfile = 'logs'+os.path.sep+'files.log' | ||
if not os.path.exists(os.path.dirname(logfile)): | ||
os.makedirs(os.path.dirname(logfile)) | ||
with open(logfile,'a') as log: | ||
log.write(md5+'\n') | ||
|
||
def localFileList(): | ||
logfile = 'logs'+os.path.sep+'files.log' | ||
if os.path.isfile(logfile): | ||
flist = open(logfile, 'r') | ||
return [line.split('\n') for line in flist.readlines()] | ||
else: | ||
open(logfile, 'w') | ||
return localFileList() | ||
|
||
def createSettingsFile(): | ||
with open('settings.cfg','w') as cfg: | ||
cfg.write('[auth]\ngmail = alias@gmail.com\npassw = yourpassword\ndevid = 0000000000000000\n\n[app]\npkg = com.whatsapp\nsig = 38a0f7d505fe18fec64fbf343ecaaaf310dbd799\n\n[client]\npkg = com.google.android.gms\nsig = 38918a453d07199354f8b19af05ec6562ced5788\nver = 9877000') | ||
|
||
|
||
def getSingleFile(data,asset): | ||
data = json.loads(data) | ||
for entries in data: | ||
if entries['f'] == asset: | ||
return entries['f'],entries['m'],entries['r'],entries['s'] | ||
|
||
def getMultipleFiles(data): | ||
files = localFileList() | ||
data = json.loads(data) | ||
for entries in data: | ||
if any(entries['m'] in lists for lists in files) == False or 'database' in entries['f'].lower(): | ||
local = 'WhatsApp'+os.path.sep+entries['f'].replace("/",os.path.sep) | ||
if os.path.isfile(local) and 'database' not in local.lower(): | ||
quit('Skipped: "'+local+'".') | ||
downloadFileGoogleDrive(bearer,'https://www.googleapis.com/drive/v2/files/'+entries['r']+'?alt=media',local) | ||
localFileLog(entries['m']) | ||
|
||
def runMain(mode,asset): | ||
global bearer | ||
if os.path.isfile('settings.cfg') == False: | ||
createSettingsFile() | ||
getConfigs() | ||
bearer = getWhatsAppAuthBearer(getGoogleAccountTokenFromAuth()) | ||
drive = gDriveFileMap() | ||
if mode == 'info': | ||
jsonPrint(drive[0]) | ||
elif mode == 'list': | ||
jsonPrint(drive[1]) | ||
elif mode == 'pull': | ||
target = getSingleFile(drive[1],asset) | ||
try: | ||
f = target[0] | ||
m = target[1] | ||
r = target[2] | ||
s = target[3] | ||
except TypeError: | ||
quit('Unable to locate: "'+asset+'".') | ||
local = 'WhatsApp'+os.path.sep+f.replace("/",os.path.sep) | ||
if os.path.isfile(local) and 'database' not in local.lower(): | ||
quit('Skipped: "'+local+'".') | ||
else: | ||
downloadFileGoogleDrive(bearer,'https://www.googleapis.com/drive/v2/files/'+r+'?alt=media',local) | ||
localFileLog(m) | ||
elif mode == 'sync': | ||
getMultipleFiles(drive[1]) | ||
|
||
def main(): | ||
args = len(sys.argv) | ||
if args < 2 or str(sys.argv[1]) == '-help' or str(sys.argv[1]) == 'help': | ||
print '\nUsage: '+str(sys.argv[0])+' -help|-vers|-info|-list|-sync|-pull file\n\nExamples:\n' | ||
print 'python '+str(sys.argv[0])+' -help (this help screen)' | ||
print 'python '+str(sys.argv[0])+' -vers (version information)' | ||
print 'python '+str(sys.argv[0])+' -info (google drive app settings)' | ||
print 'python '+str(sys.argv[0])+' -list (list all availabe files)' | ||
print 'python '+str(sys.argv[0])+' -sync (sync all files locally)' | ||
print 'python '+str(sys.argv[0])+' -pull "Databases/msgstore.db.crypt12" (download)\n' | ||
elif str(sys.argv[1]) == '-info' or str(sys.argv[1]) == 'info': | ||
runMain('info','settings') | ||
elif str(sys.argv[1]) == '-list' or str(sys.argv[1]) == 'list': | ||
runMain('list','all') | ||
elif str(sys.argv[1]) == '-sync' or str(sys.argv[1]) == 'sync': | ||
runMain('sync','all') | ||
elif str(sys.argv[1]) == '-vers' or str(sys.argv[1]) == 'vers': | ||
print '\n'+__product__+' Version '+str(__version__)+' '+__copyright__+' by '+__author__+'\n' | ||
elif args <> 3: | ||
quit('\nUsage: python '+str(sys.argv[0])+' -help|-vers|-info|-list|-sync|-pull file\n') | ||
elif str(sys.argv[1]) == '-pull' or str(sys.argv[1]) == 'pull': | ||
runMain('pull',str(sys.argv[2])) | ||
else: | ||
quit('\nUsage: python '+str(sys.argv[0])+' -help|-vers|-info|-list|-sync|-pull file\n') | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[auth] | ||
gmail = alias@gmail.com | ||
passw = yourpassword | ||
devid = 0000000000000000 | ||
|
||
[app] | ||
pkg = com.whatsapp | ||
sig = 38a0f7d505fe18fec64fbf343ecaaaf310dbd799 | ||
|
||
[client] | ||
pkg = com.google.android.gms | ||
sig = 38918a453d07199354f8b19af05ec6562ced5788 | ||
ver = 9877000 |