import time from flask import Flask, request import requests from PIL import ImageFile, Image import os import shutil import subprocess from zipfile import ZipFile ImageFile.SAFEBLOCK = 2048 * 2048 app = Flask(__name__) app.base_project = "/Users/akhmadalqindiirsyam/Documents/WorkFolder/AppBuilder/appbuilder-ios/AppBuilder" app.nexilis_lite = "/Users/akhmadalqindiirsyam/Documents/WorkFolder/AppBuilder/appbuilder-ios/NexilisLite" app.temp_folder = "/Users/akhmadalqindiirsyam/Documents/WorkFolder/BuildIos" app.app_folder = "/Users/akhmadalqindiirsyam/Documents/WorkFolder" app.asset_folder = "/Users/akhmadalqindiirsyam/Documents/WorkFolder/BuildIosAssets" app.verbose = True app.ssl = None app.keytool = '/usr/bin/keytool' app.username = "akhmadalqindiirsyam" # app.ios_platform_ids = ["bb8f256703e8fbe84da414cee20cb4d0eca3388d"] app.ios_platform_ids = [] app.app_name = "AppBuilder" app.package_id = "io.newuniverse.AppBuilder" app.version_code = "1" app.version_name = "1.0.0" app.base_project_name = os.path.basename(app.base_project) def vprint(*data): if app.verbose: print(*data) def create_folder(package_id,app_name): path = os.path.join(app.temp_folder, package_id) if not os.path.exists(path): os.mkdir(path) else: shutil.rmtree(path) os.mkdir(path) vprint(path) lib_dest = os.path.join(path, "NexilisLite") if not os.path.exists(lib_dest): shutil.copytree(app.nexilis_lite, lib_dest) path_dest = os.path.join(path, app.base_project_name) if not os.path.exists(path_dest): shutil.copytree(app.base_project, path_dest) c_code_path = os.path.join(path_dest,app_name) orig_code_path = os.path.join(path_dest,"AppBuilder") if not os.path.exists(c_code_path): shutil.copytree(orig_code_path, c_code_path) shutil.rmtree(orig_code_path) return path_dest, c_code_path, lib_dest def change_acc(c_code_path, acc): main_activity = os.path.join(c_code_path, "AppDelegate.swift") with open(main_activity, "r") as f: file_source = f.read() replaced = file_source.replace("***REPLACE***WITH***YOUR***ACCOUNT***", acc) with open(main_activity, "w") as f: f.write(replaced) def change_url(c_code_path, url): main_activity = os.path.join(c_code_path, "ViewController.swift") with open(main_activity, "r") as f: file_source = f.read() replaced = file_source.replace("https://www.google.com", url) with open(main_activity, "w") as f: f.write(replaced) def change_name(path_dest, app_name, package_id): xcproj = os.path.join(path_dest, "{}.xcodeproj".format(app_name)) xcwork = os.path.join(path_dest, "{}.xcworkspace".format(app_name)) shutil.move(os.path.join(path_dest, "AppBuilder.xcodeproj"), xcproj) # shutil.move(os.path.join(path_dest, "AppBuilder.xcworkspace"), xcwork) xcshareddata = os.path.join(xcproj, "xcshareddata/xcschemes", "{}.xcscheme".format(app_name)) shutil.move(os.path.join(xcproj, "xcshareddata/xcschemes", "AppBuilder.xcscheme"), xcshareddata) podfile = os.path.join(path_dest, "Podfile") with open(podfile, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(podfile, "w") as f: f.write(replaced) info_plist = os.path.join(path_dest,app_name,"Info.plist") with open(info_plist, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(info_plist, "w") as f: f.write(replaced) main_stry = os.path.join(path_dest, app_name, "Base.lproj/Main.storyboard") with open(main_stry, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(main_stry, "w") as f: f.write(replaced) project = os.path.join(xcproj, "project.pbxproj") package_rep = "io.newuniverse.{}".format(app_name) with open(project, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) replaced = replaced.replace(package_rep, package_id) with open(project, "w") as f: f.write(replaced) with open(xcshareddata, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(xcshareddata, "w") as f: f.write(replaced) xcuserdata = os.path.join(xcproj, "xcuserdata/{}.xcuserdatad/xcschemes/xcschememanagement.plist".format(app.username)) try: with open(xcuserdata, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(xcuserdata, "w") as f: f.write(replaced) except FileNotFoundError: pass os.chdir(path_dest) subprocess.run(["pod", "install"]) contentsw = os.path.join(xcwork, "contents.xcworkspacedata") with open(contentsw, "r") as f: file_source = f.read() replaced = file_source.replace("AppBuilder", app_name) with open(contentsw, "w") as f: f.write(replaced) def change_certificate(path_dest, key, keystore, keytool): pass def change_package(path_dest, package_id): pass def change_version(path_dest, app_name, version_code, version_name): project = os.path.join(path_dest, '{}.xcodeproj'.format(app_name), 'project.pbxproj') with open(project, "r") as f: file_source = f.read() replaced = file_source.replace("CURRENT_PROJECT_VERSION = 1;", "CURRENT_PROJECT_VERSION = {};".format(version_code)) replaced = replaced.replace('MARKETING_VERSION = 1.0.0;', 'MARKETING_VERSION = {};'.format(version_name)) with open(project, "w") as f: f.write(replaced) def change_font(c_code_path, font): prefs_path = os.path.join(c_code_path, "AppDelegate.swift") with open(prefs_path, "r") as f: file_source = f.read() replaced = file_source.replace("FONT_SELECT = 0", "FONT_SELECT = {}".format(font)) with open(prefs_path, "w") as f: f.write(replaced) pass def change_logo(c_code_path, lib_dest, logo, logo_float=None): app_icon_set = [29,40,57,58,60,80,87,114,120,180,1024] app_icon_dir = os.path.join(c_code_path, 'Assets.xcassets/AppIcon.appiconset') app_float_dir = os.path.join(lib_dest, 'NexilisLite/Resource/Assets.xcassets/pb_button.imageset') app_launch_dir = os.path.join(c_code_path, 'Assets.xcassets/pb_icon.imageset') if isinstance(logo, str): # try: # logo_url = requests.get('https://newuniverse.io/dashboardv2/uploads/logo/{}'.format(logo)) # for size in app_icon_set: # img_path = os.path.join(app_icon_dir, "{}.png".format(size)) # with open(img_path, "wb") as f: # f.write(logo_url.content) # with open(img_path, "rb") as f: # l = Image.open(f) # l = l.resize((size, size)) # l.save(img_path, "PNG") # except: try: logo_path = os.path.join(app.asset_folder, "logo", "{}".format(logo)) for size in app_icon_set: img_path = os.path.join(app_icon_dir, "{}.png".format(size)) with open(logo_path, "rb") as f: l = Image.open(f) l = l.resize((size, size)) l.save(img_path, "PNG") except: print("error logo: {}".format(logo)) return if logo_float: # try: # logo_float_url = requests.get('https://newuniverse.io/dashboardv2/uploads/logofloat/{}'.format(logo_float)) # img_path = os.path.join(app_float_dir, "pb_ball.png") # with open(img_path, "wb") as f: # f.write(logo_float_url.content) # with open(img_path, "rb") as f: # l = Image.open(f) # l = l.resize((512, 512)) # l.save(img_path, "PNG") # except: try: logo_launch_path = os.path.join(app.asset_folder, "logofloat", "{}".format(logo_float)) img_path = os.path.join(app_launch_dir, "nexilis_icon.png".format(size)) with open(logo_launch_path, "rb") as f: l = Image.open(f) l = l.resize((size, size)) l.save(img_path, "PNG") except: print("error logolaunch: {}".format(logo_float)) return try: logo_float_path = os.path.join(app.asset_folder, "logofloat", "{}".format(logo_float)) img_path = os.path.join(app_float_dir, "pb_button.png".format(size)) with open(logo_float_path, "rb") as f: l = Image.open(f) l = l.resize((size, size)) l.save(img_path, "PNG") except: print("error logofloat: {}".format(logo_float)) return else: logo = Image.open(logo) for size in app_icon_set: img_path = os.path.join(app_icon_dir, "{}.png".format(size)) logo_resized = logo.resize((size,size)) logo_resized.save(img_path, "PNG") if logo_float: logo_float = Image.open(logo_float) img_path = os.path.join(app_float_dir, "nexilis_icon.png") logo_float_resized = logo_float.resize((512,512)) logo_float_resized.save(img_path, "PNG") def change_background(c_code_path, background): # assets_dir = os.path.join(c_code_path, "Assets.xcassets") # img_src_path_1 = os.path.join(assets_dir, "pb_lbackground_1.imageset") # if isinstance(background, str): # background = background.split(",") # for i, b in enumerate(background): # n = i + 1 # print(b) # img_src_path = os.path.join(assets_dir, "pb_lbackground_{}.imageset".format(n)) # print(img_src_path) # if n != 1: # shutil.copytree(img_src_path_1,img_src_path) # os.remove(os.path.join(img_src_path,"pb_lbackground_1.png")) # contents_json = os.path.join(img_src_path, "Contents.json") # with open(contents_json, "r") as f: # file_source = f.read() # replaced = file_source.replace("lbackground_1", "lbackground_{}".format(n)) # with open(contents_json, "w") as f: # f.write(replaced) # img_path = os.path.join(img_src_path, "pb_lbackground_{}.png".format(n)) # # try: # # background_url = requests.get('https://newuniverse.io/dashboardv2/uploads/background/{}'.format(b)) # # with open(img_path, "wb") as f: # # f.write(background_url.content) # # with open(img_path, "rb") as f: # # l = Image.open(f) # # l = l.resize((600, 1250)) # # l.save(img_path, "PNG") # # except: # try: # background_path = os.path.join(app.asset_folder, "background", "{}".format(b)) # with open(background_path, "rb") as f: # l = Image.open(f) # l = l.resize((600, 1250)) # l.save(img_path, "PNG") # except: # print("error background: {}".format(b)) # return # second_tab = os.path.join(c_code_path, "SecondTabViewController.swift") # fourth_tab = os.path.join(c_code_path, "FourthTabViewController.swift") # with open(second_tab, "r") as f: # file_source = f.read() # replaced = file_source.replace("1..<2", "1..<{}".format(len(background) + 1)) # with open(second_tab, "w") as f: # f.write(replaced) # with open(fourth_tab, "r") as f: # file_source = f.read() # replaced = file_source.replace("1..<2", "1..<{}".format(len(background) + 1)) # with open(fourth_tab, "w") as f: # f.write(replaced) # else: # img_path = os.path.join(img_src_path_1, "pb_lbackground_1.png") # logo = Image.open(background) # logo = logo.resize((600, 1250)) # logo.save(img_path, "PNG") pass def change_fb(lib_dest, fb_icon): default_fb_icon = ["pb_button_chat", "pb_button_call", "pb_button_cc", "pb_button_post", "pb_button_stream"] for i in range(5): if not fb_icon[i]: continue img_path = "NexilisLite/Resource/Assets.xcassets" img_path = os.path.join(lib_dest, img_path, "{}.imageset".format(default_fb_icon[i]), "{}.png".format(default_fb_icon[i])) if isinstance(fb_icon[i], str): # try: # fb_icon_url = requests.get('https://newuniverse.io/dashboardv2/uploads/fb_icon/{}'.format(fb_icon[i])) # with open(img_path, "wb") as f: # f.write(fb_icon_url.content) # with open(img_path, "rb") as f: # l = Image.open(f) # l = l.resize((150, 150)) # l.save(img_path, "PNG") # except: try: fb_icon_path = os.path.join(app.asset_folder, "fb_icon", "{}".format(fb_icon[i])) with open(fb_icon_path, "rb") as f: l = Image.open(f) l = l.resize((150, 150)) l.save(img_path, "PNG") except: print("error tab icon {}: {}".format(i,fb_icon[i])) else: logo = Image.open(fb_icon[i]) logo = logo.resize((150, 150)) logo.save(img_path, "PNG") def change_access(c_code_path, access_model): access = ["CPAAS_MODE_FLOATING", "CPAAS_MODE_DOCKED", "CPAAS_MODE_BURGER"] code_path = os.path.join(c_code_path, "PrefsUtil.swift") print(code_path) with open(code_path, "r") as f: file_source = f.read() acc = "CPAAS_MODE_MIX" if access_model > 2 else access[access_model] replaced = file_source.replace("= CPAAS_MODE_DOCKED", "= {}".format(acc)) with open(code_path, "w") as f: f.write(replaced) pass def change_tab(c_code_path, tabs, tab_icon, tab3_mode): default_tab_icon = ["tab_1", "tab_2", "tab_3", "tab_4"] for i in range(4): if not tab_icon[i]: continue img_path = os.path.join(c_code_path, "Assets.xcassets", "{}_icon.imageset".format(default_tab_icon[i]), "{}_nexilis.png".format(default_tab_icon[i])) if isinstance(tab_icon[i], str): # try: # tab_icon_url = requests.get('https://newuniverse.io/dashboardv2/uploads/tab_icon/{}'.format(tab_icon[i])) # with open(img_path, "wb") as f: # f.write(tab_icon_url.content) # with open(img_path, "rb") as f: # l = Image.open(f) # l = l.resize((150, 150)) # l.save(img_path, "PNG") # except: try: tab_icon_path = os.path.join(app.asset_folder, "tab_icon", "{}".format(tab_icon[i])) with open(tab_icon_path, "rb") as f: l = Image.open(f) l = l.resize((150, 150)) l.save(img_path, "PNG") except: print("error tab_icon {}: {}".format(i,tab_icon[i])) return else: logo = Image.open(tab_icon[i]) logo = logo.resize((150, 150)) logo.save(img_path, "PNG") prefs_util = os.path.join(c_code_path, "PrefsUtil.swift") with open(prefs_util, "r") as f: file_source = f.read() replaced = file_source.replace("1,2,3,4", ",".join(tabs)) with open(prefs_util, "w") as f: f.write(replaced) main_code_path = os.path.join(c_code_path, "ViewController.swift") with open(main_code_path, "r") as f: file_source = f.read() replaced = file_source.replace('tab3 = "0"', 'tab3 = "{}"'.format(tab3_mode)) with open(main_code_path, "w") as f: f.write(replaced) def run_build(path_dest, app_name): workspace = os.path.join(path_dest, "{}.xcworkspace".format(app_name)) build_args = ["xcodebuild", "clean", "build", "-scheme", app_name, "-workspace", workspace] install_args = ["xcodebuild", "clean", "install", "-scheme", app_name, "-workspace", workspace] ret = -1 if(len(app.ios_platform_ids) > 0): for id in app.ios_platform_ids: build_args_run = install_args build_args_run.append("-destination") build_args_run.append('platform=iOS,id={}'.format(id)) print(build_args_run) ret = subprocess.run(build_args_run) if ret.returncode != 0: break return ret.returncode else: ret = subprocess.run(build_args) if ret.returncode == 0: # ret = subprocess.run(["xcodebuild", "-workspace", workspace, "-scheme", app_name, # "-archivePath", os.path.join(path_dest, "out", "{}.xcarchive".format(app_name)), # "archive"]) return ret.returncode return ret.returncode def deliver_app(path_dest, app_name, package_id, key, key_exists): archive_dir = os.path.join(path_dest, 'out', "{}.archive".format(app_name)) timenow = time.time() archive_name = "{}{}.xarchive".format(package_id, timenow) zip_name = "{}{}.zip".format(package_id, timenow) new_arc_dir = os.path.join(app.app_folder, archive_name) new_dir = os.path.join(app.app_folder, zip_name) vprint(archive_dir) try: shutil.move(archive_dir, new_arc_dir) with ZipFile(new_dir, 'w') as zip_file: zip_file.write(new_arc_dir, os.path.basename(new_arc_dir)) # os.remove(new_arc_dir) project_path = os.path.join(app.temp_folder, package_id) # shutil.rmtree(project_path) return {"name": zip_name} except Exception as e: return str(e) @app.route('/', methods=["GET", "POST"]) def build_apk(): vprint('==============================================================') if request.method == 'POST': logo = None logo_float = None app_name = app.app_name package_id = app.package_id acc = None url = None keystore = None key_exists = False # tabs = ["1", "2", "3", "4"] tabs = [] tab3_mode = "0" tab_icon = [None, None, None, None] fb_icon = [None, None, None, None, None] background = None version_code = app.version_code version_name = app.version_name font = 0 key = {"alias": "nexilislite", "store_password": "allyourbase", "key_password": "arebelongto", "common_name": "all", "organization_unit": "your", "organization_name": "base", "locality_name": "are", "state_name": "belong", "country": "to"} if 'logo' in request.files: logo = request.files['logo'] vprint(type(logo)) elif 'logo' in request.form: logo = request.form['logo'] vprint(type(logo)) if 'logofloat' in request.files: logo_float = request.files['logofloat'] vprint(type(logo_float)) elif 'logofloat' in request.form: logo_float = request.form['logofloat'] vprint(type(logo_float)) if 'app_name' in request.files: app_name = request.files['app_name'] vprint(app_name) elif 'app_name' in request.form: app_name = request.form['app_name'] vprint(app_name) if 'package_id' in request.files: package_id = request.files['package_id'] vprint(package_id) elif 'package_id' in request.form: package_id = request.form['package_id'] vprint(package_id) if 'acc' in request.files: acc = request.files['acc'] vprint(acc) elif 'acc' in request.form: acc = request.form['acc'] vprint(acc) if 'url' in request.files: url = request.files['url'] vprint(url) elif 'url' in request.form: url = request.form['url'] vprint(url) if 'keystore' in request.files: keystore = request.files['keystore'] key_exists = True elif 'keystore' in request.form: keystore = request.form['keystore'] key_exists = True if 'alias' in request.form: if request.form['alias']: key["alias"] = request.form['alias'] if 'store_password' in request.form: if request.form['store_password']: key["store_password"] = request.form['store_password'] if 'key_password' in request.form: if request.form['key_password']: key["key_password"] = request.form['key_password'] if keystore: if 'common_name' in request.form: if request.form['common_name']: key["common_name"] = request.form['common_name'] if 'organization_unit' in request.form: if request.form['organization_unit']: key["organization_unit"] = request.form['organization_unit'] if 'organization_name' in request.form: if request.form['organization_name']: key["organization_name"] = request.form['organization_name'] if 'locality_name' in request.form: if request.form['locality_name']: key["locality_name"] = request.form['locality_name'] if 'state_name' in request.form: if request.form['state_name']: key["state_name"] = request.form['state_name'] if 'country' in request.form: if request.form['country']: key["country"] = request.form['country'] tabs.append(request.form["tab1"]) tabs.append(request.form["tab2"]) if request.form['tab3']: tabs.append(request.form["tab3"]) if request.form['tab4']: tabs.append(request.form["tab4"]) if 'tab1_icon' in request.files: tab_icon[0] = request.files['tab1_icon'] elif 'tab1_icon' in request.form: tab_icon[0] = request.form['tab1_icon'] if 'tab2_icon' in request.files: tab_icon[1] = request.files['tab2_icon'] elif 'tab2_icon' in request.form: tab_icon[1] = request.form['tab2_icon'] if 'tab3_icon' in request.files: tab_icon[2] = request.files['tab3_icon'] elif 'tab3_icon' in request.form: tab_icon[2] = request.form['tab3_icon'] if 'tab4_icon' in request.files: tab_icon[3] = request.files['tab4_icon'] elif 'tab4_icon' in request.form: tab_icon[3] = request.form['tab4_icon'] if 'fb1_icon' in request.files: fb_icon[0] = request.files['fb1_icon'] elif 'fb1_icon' in request.form: fb_icon[0] = request.form['fb1_icon'] if 'fb2_icon' in request.files: fb_icon[1] = request.files['fb2_icon'] elif 'fb2_icon' in request.form: fb_icon[1] = request.form['fb2_icon'] if 'fb3_icon' in request.files: fb_icon[2] = request.files['fb3_icon'] elif 'fb3_icon' in request.form: fb_icon[2] = request.form['fb3_icon'] if 'fb4_icon' in request.files: fb_icon[3] = request.files['fb4_icon'] elif 'fb4_icon' in request.form: fb_icon[3] = request.form['fb4_icon'] if 'fb5_icon' in request.files: fb_icon[4] = request.files['fb5_icon'] elif 'fb5_icon' in request.form: fb_icon[4] = request.form['fb5_icon'] vprint("fb_icon: {}".format(fb_icon)) access_model = int(request.form['access_model']) if 'tab3_mode' in request.form: tab3_mode = request.form['tab3_mode'] if 'tab_amount' in request.form: tab_amount = int(request.form['tab_amount']) if 'font' in request.form: font = int(request.form['font']) if 'background' in request.files: background = request.files['background'] elif 'background' in request.form: background = request.form['background'] if 'version_code' in request.form: version_code = request.form['version_code'] if 'version_name' in request.form: version_name = request.form['version_name'] else: version_name = "1.0.{}".format(version_code) derived_data = os.path.join(app.app_folder, 'Library/Developer/Xcode/DerivedData') if os.path.exists(derived_data): shutil.rmtree(derived_data,ignore_errors=True) path_dest, c_code_path, lib_dest = create_folder(package_id, app_name) vprint("path_dest: " + path_dest) vprint("c_code_path: " + c_code_path) if app_name != "AppBuilder": change_name(path_dest, app_name, package_id) if acc: change_acc(c_code_path, acc) if url: change_url(c_code_path, url) # change_certificate(path_dest, key, keystore, app.keytool) # change_package(path_dest, package_id) change_version(path_dest, app_name, version_code, version_name) change_font(c_code_path, font) if logo: change_logo(c_code_path, lib_dest, logo, logo_float) if background: change_background(c_code_path, background) change_fb(lib_dest, fb_icon) change_access(c_code_path, access_model) change_tab(c_code_path, tabs, tab_icon, tab3_mode) os.chdir(path_dest) return_code = run_build(path_dest,app_name) # if (return_code == 0): # return deliver_app(path_dest, app_name, package_id, key, key_exists) return {'return_code': return_code} else: if 'e' in request.args: return request.args['e'] return "Hello World!" if __name__ == '__main__': app.run(host='0.0.0.0', port=8093, debug=app.verbose, ssl_context=app.ssl)