2023-08-08 23:33:09 -05:00
#!/usr/bin/env python3
2023-08-10 15:49:03 -05:00
# SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra@ou.edu>
# SPDX-License-Identifier: GPL-3.0-only
2023-08-08 23:33:09 -05:00
import sys
import os
import configparser as cp
import requests as req
import json
from packaging . version import Version
from APKPure_dl import *
2023-08-09 02:17:29 -05:00
from JAVABuilder import *
2023-08-09 14:25:32 -05:00
from datetime import datetime
2023-08-09 19:12:04 -05:00
from Notifications import send_notif
from Cleanup import *
2023-08-10 14:50:42 -05:00
import logging
2023-08-10 14:52:58 -05:00
import subprocess
2023-08-09 02:17:29 -05:00
# TODO: README
2023-08-09 19:12:04 -05:00
# TODO: PATCHES_GUIDE.md (maybe delete it?)
2023-08-10 15:20:40 -05:00
# TODO: Install using pip
2023-08-08 23:33:09 -05:00
# Update the ReVanced tools, if needed
2023-08-09 19:12:04 -05:00
def update_tools ( appstate ) :
2023-08-08 23:33:09 -05:00
for item in [ ' revanced-cli ' , ' revanced-integrations ' , ' revanced-patches ' ] :
* _ , tool = filter ( lambda x : x [ ' repository ' ] == ' revanced/ ' + item , tools ) # Get the last result
latest_ver = Version ( tool [ ' version ' ] )
try :
2023-08-09 19:12:04 -05:00
present_ver = Version ( appstate [ ' present_vers ' ] [ item ] )
2023-08-08 23:33:09 -05:00
except KeyError :
present_ver = Version ( ' 0 ' )
2023-08-09 02:17:29 -05:00
output_file = item + os . path . splitext ( tool [ ' name ' ] ) [ 1 ]
if flag == ' force ' or not os . path . isfile ( output_file ) or present_ver < latest_ver :
2023-08-09 19:12:04 -05:00
appstate [ ' up-to-date ' ] = False
2023-08-08 23:33:09 -05:00
print ( f " { item } has an update ( { str ( present_ver ) } -> { str ( latest_ver ) } ) " )
if flag != ' checkonly ' :
print ( f " Downloading { output_file } ... " )
res = req . get ( tool [ ' browser_download_url ' ] , stream = True )
res . raise_for_status ( )
with open ( output_file , ' wb ' ) as f :
for chunk in res . iter_content ( chunk_size = 8192 ) :
f . write ( chunk )
2023-08-09 19:12:04 -05:00
appstate [ ' present_vers ' ] . update ( { item : str ( latest_ver ) } )
2023-08-08 23:33:09 -05:00
print ( " Done! " )
2023-08-09 19:12:04 -05:00
return appstate
2023-08-08 23:33:09 -05:00
# Update microG, if needed
2023-08-09 19:12:04 -05:00
def update_microg ( appstate ) :
2023-08-08 23:33:09 -05:00
try :
data = req . get ( ' https://api.github.com/repos/inotia00/VancedMicroG/releases/latest ' ) . json ( ) [ ' tag_name ' ]
latest_ver = Version ( data )
except req . exceptions . RequestException as e :
2023-08-09 19:12:04 -05:00
clean_exit ( e , appstate )
2023-08-08 23:33:09 -05:00
try :
2023-08-09 19:12:04 -05:00
present_ver = Version ( appstate [ ' present_vers ' ] [ ' VancedMicroG ' ] )
2023-08-08 23:33:09 -05:00
except KeyError :
present_ver = Version ( ' 0 ' )
2023-08-09 02:17:29 -05:00
if flag == ' force ' or not os . path . isfile ( ' microg.apk ' ) or present_ver < latest_ver :
2023-08-09 19:12:04 -05:00
appstate [ ' up-to-date ' ] = False
2023-08-08 23:33:09 -05:00
print ( f " Vanced microG has an update ( { str ( present_ver ) } -> { str ( latest_ver ) } ) " )
if flag != ' checkonly ' :
2023-08-09 02:17:29 -05:00
print ( f " Downloading vanced-microg.apk... " )
2023-08-08 23:33:09 -05:00
res = req . get ( ' https://github.com/inotia00/VancedMicroG/releases/latest/download/microg.apk ' , stream = True )
res . raise_for_status ( )
with open ( ' microg.apk ' , ' wb ' ) as f :
for chunk in res . iter_content ( chunk_size = 8192 ) :
f . write ( chunk )
2023-08-09 19:12:04 -05:00
appstate [ ' present_vers ' ] . update ( { ' VancedMicroG ' : str ( latest_ver ) } )
2023-08-08 23:33:09 -05:00
print ( " Done! " )
2023-08-10 13:07:00 -05:00
appstate [ ' microg_updated ' ] = True
2023-08-08 23:33:09 -05:00
2023-08-09 19:12:04 -05:00
return appstate
2023-08-09 14:25:32 -05:00
# ------------------------------
# The main function starts here
# ------------------------------
2023-08-09 19:12:04 -05:00
# Create a dict for storing important data
appstate = { }
2023-08-09 14:25:32 -05:00
# Get a timestamp
time = datetime . now ( )
2023-08-09 19:12:04 -05:00
appstate [ ' timestamp ' ] = time . strftime ( ' % Y % m %d % H % M % S ' )
2023-08-09 14:25:32 -05:00
2023-08-10 14:50:42 -05:00
# Read arguments
2023-08-08 23:33:09 -05:00
try :
os . chdir ( sys . argv [ 1 ] )
except IndexError :
2023-08-09 19:12:04 -05:00
clean_exit ( ' Please provide a working directory as argument! ' , appstate )
2023-08-08 23:33:09 -05:00
except FileNotFoundError :
2023-08-09 19:12:04 -05:00
clean_exit ( ' Invalid working directory provided! ' , appstate )
2023-08-08 23:33:09 -05:00
2023-08-10 15:12:22 -05:00
# Try to make sure only one instance is running in a given working directory
try :
if os . path . exists ( ' lockfile ' ) :
raise FileExistsError
with open ( ' tmplockfile ' , ' x ' ) as f :
f . flush ( )
os . fsync ( f . fileno ( ) )
os . replace ( ' tmplockfile ' , ' lockfile ' )
except FileExistsError :
sys . exit ( ' Another instance is already running in the same working directory! ' )
2023-08-10 14:50:42 -05:00
# Set up logging
try :
os . mkdir ( ' logs ' )
except FileExistsError :
pass
logging . basicConfig ( level = logging . INFO , format = ' %(message)s ' )
logger = logging . getLogger ( )
logger . addHandler ( logging . FileHandler ( f " logs/ { appstate [ ' timestamp ' ] } .log " , ' w ' ) )
print = logger . info
appstate [ ' logger ' ] = logger
# Get the flag
2023-08-08 23:33:09 -05:00
try :
flag = sys . argv [ 2 ]
except :
flag = None
2023-08-10 15:20:40 -05:00
if flag not in [ ' buildonly ' , ' checkonly ' , ' force ' , ' experimental ' , None ] :
2023-08-10 14:50:42 -05:00
clean_exit ( f " Unknown flag: { flag } " , appstate )
2023-08-09 19:12:04 -05:00
appstate [ ' flag ' ] = flag
2023-08-10 13:07:00 -05:00
appstate [ ' microg_updated ' ] = False
2023-08-09 19:12:04 -05:00
2023-08-10 14:50:42 -05:00
print ( f " Started building ReVanced apps at { time . strftime ( ' %d % B, % Y % H: % M: % S ' ) } " )
print ( ' ---------------------------------------------------------------------- ' )
# Read configs
2023-08-08 23:33:09 -05:00
try :
2023-08-09 19:12:04 -05:00
appstate [ ' build_config ' ] = cp . ConfigParser ( )
appstate [ ' build_config ' ] . read_file ( open ( ' build_config.toml ' , ' r ' ) )
2023-08-08 23:33:09 -05:00
except FileNotFoundError :
2023-08-09 19:12:04 -05:00
clean_exit ( ' No build config provided, exiting. Please look at the GitHub page for more information: \n https://github.com/SinTan1729/ReVancedBuilder ' , appstate )
2023-08-08 23:33:09 -05:00
2023-08-09 19:12:04 -05:00
appstate [ ' notification_config ' ] = cp . ConfigParser ( )
appstate [ ' notification_config ' ] . read ( ' notification_config.toml ' )
2023-08-08 23:33:09 -05:00
# Pull the latest information using the ReVanced API
try :
tools = req . get ( ' https://releases.revanced.app/tools ' ) . json ( ) [ ' tools ' ]
except req . exceptions . RequestException as e :
2023-08-09 19:12:04 -05:00
clean_exit ( e , appstate )
2023-08-08 23:33:09 -05:00
try :
with open ( ' versions.json ' , ' r ' ) as f :
2023-08-09 19:12:04 -05:00
appstate [ ' present_vers ' ] = json . load ( f )
2023-08-08 23:33:09 -05:00
except :
# We'll treat empty as 0 later
2023-08-09 19:12:04 -05:00
appstate [ ' present_vers ' ] = json . loads ( ' {} ' )
2023-08-08 23:33:09 -05:00
2023-08-09 19:12:04 -05:00
appstate [ ' up-to-date ' ] = True
# send_notif(appstate, error=False) # <,,,,,,,,<,,,,,,,,,,,,,
2023-08-08 23:33:09 -05:00
if flag != ' buildonly ' :
2023-08-09 19:12:04 -05:00
appstate = update_tools ( appstate )
appstate = update_microg ( appstate )
if not appstate [ ' up-to-date ' ] or flag == ' force ' :
appstate = get_apks ( appstate )
2023-08-08 23:33:09 -05:00
2023-08-09 19:12:04 -05:00
if ( flag != ' checkonly ' and not appstate [ ' up-to-date ' ] ) or flag in [ ' force ' , ' buildonly ' ] :
build_apps ( appstate )
move_apps ( appstate )
2023-08-08 23:33:09 -05:00
# Update version numbers in the versions.json file
2023-08-09 19:12:04 -05:00
if appstate [ ' up-to-date ' ] and flag != ' buildonly ' :
2023-08-08 23:33:09 -05:00
print ( ' There \' s nothing to do. ' )
2023-08-09 19:12:04 -05:00
elif flag != [ ' checkonly ' ] :
send_notif ( appstate )
try :
os . rename ( ' versions.json ' , ' versions-old.json ' )
except FileNotFoundError :
pass
if flag != ' buildonly ' :
with open ( ' versions.json ' , ' w ' ) as f :
json . dump ( appstate [ ' present_vers ' ] , f , indent = 4 )
2023-08-10 14:52:58 -05:00
try :
subprocess . run ( f " { appstate [ ' build_config ' ] [ ' post_script ' ] [ ' file ' ] } { timestamp } " , shell = True )
except :
pass
2023-08-10 15:12:22 -05:00
# Delete the lockfile
os . remove ( ' lockfile ' )