def validate_driver_images(android_path: str) -> bool: if not os.path.exists(android_path): raise PathError(subcode=PathError.path_not_found, data=PathError.path_not_found_mes % android_path) valid_dirs = ['ic_launcher', 'gootax', 'push', 'splash'] dpi = ["-mdpi", "-hdpi", "-xhdpi", "-xxhdpi"] png = ".png" dir_list = list(map(lambda x: str(x).lower(), os.listdir(android_path))) logging.info("Resource with path {%s} have {%s} folders" % (android_path, dir_list)) for direct in valid_dirs: if direct not in dir_list: raise ResourceError(subcode=ResourceError.android_folder, data=ResourceError.android_folder_mes % direct) for img_folder in dir_list: folder_path = merge(android_path, img_folder) if img_folder == "__MACOSX": continue if img_folder not in valid_dirs: try: shutil.rmtree(folder_path) except NotADirectoryError: os.remove(folder_path) continue images = list(map(lambda x: str(x).lower(), os.listdir(folder_path))) logging.info("Resource {%s} have {%s} images" % (img_folder, images)) for image in images: if not image.startswith(img_folder): os.remove(merge(folder_path, image)) for image_dpi in dpi: file = img_folder + image_dpi + png logging.info("Checking {%s} file" % file) if file not in images: raise ResourceError(subcode=ResourceError.android_image, data=ResourceError.android_image_mes % file) return True
def generate_zip_res(self, file, name: str, res_type: str) -> None: path_temp_res = merge(self.temp_path, name) path_temp_type = merge(self.temp_path, name, res_type) path_res_type = merge(self.res_path, name, res_type) zip_name = name + "-" + res_type + ".zip" if res.allowed_zip(file.filename): res.unzip_temp(file, zip_name, path_temp_res, res_type) try: # Validation and store files self.validate_res_by_type(res_type, path_temp_type) if res_type == IOS: from std.migration import ios_image_migrate try: ios_image_migrate.create_logo_content( path_temp_type, path_res_type) except Exception: raise ResourceError( subcode=ResourceError.res_not_found, data=ResourceError.ios_image_res) elif res_type == ANDROID or res_type == ANDROID_DRIVER or res_type == ANDROID_DRIVER_NEW: res.save_temp(path_temp_type, path_res_type) else: raise ResourceError(subcode=ResourceError.res_not_found, data=ResourceError.res_not_found_mes % res_type) # Create ZIP for Google path = merge(path_temp_res, parse_sku(name) + "-" + res_type) res.create_zip_res(path_res_type, path) # Load to Google gzip_name = parse_sku(name) + "-" + res_type + ".zip" gzip_path = merge(path_temp_res, gzip_name) disk: Disk = GoogleDisk(with_auth=True) disk.replace_file(gzip_path, gzip_name, disk.get_folder_id_by_name(name)) # Delete temp res.delete(path_temp_res) except ResourceError as error: # res.delete(path_temp_res) raise error else: raise ResourceError(subcode=ResourceError.file_type, data=ResourceError.file_type_mes % (file.filename, "zip"))
def get_apk_path(bundle, is_new): type = "/release" if is_new else "" path = merge(config.FINISH_PATH, "gootax_app_android_" + bundle.replace(".", "_"), "app/build/outputs/apk" + type + "/app-release.apk") logging.info("APK path " + path) return path
def __init__(self, application, theme, params): # Entity self.application: Application = application self.theme: Theme = theme # Build params self.need_build = validate_field( params[build_params_scheme.id_need_build]) self.need_clear = validate_field( params[build_params_scheme.id_need_clear]) self.create_app = validate_field( params[build_params_scheme.id_create_app]) self.version_name = validate_field( params[build_params_scheme.id_version_name]) self.version_code = validate_field( params[build_params_scheme.id_version_code]) self.bundle = validate_field(params[build_params_scheme.id_def_bundle]) self.email = validate_field(params[build_params_scheme.id_email]) # Build paths self.finish_path = self.get_final_path(application.bundle) self.params_path = self.get_android_params_path( self.finish_path, application.bundle) self.res_path = merge(config.RES_PATH, application.bundle) self.country = am.get_country(application.country) self.new_bundle = application.bundle
def replace_strings(self, bundle, new_bundle): print(f"old {bundle}") print(f"new {new_bundle}") # Begin function begin_time = time.time() project_path = self.final_path count_total = 0 total_replace = 0 count_error = 0 for path, dirs, files in os.walk(project_path, True): for cur_name in files: count_total += 1 file_path = merge(path, cur_name) try: text = open(file_path).read() if bundle in text: open(file_path, 'w').write(text.replace(bundle, new_bundle)) total_replace += 1 except ValueError: count_error += 1 # End function work end_time = time.time() executing_time = end_time - begin_time logging.info(info.FILE_REPLACE % (str(count_total), str(total_replace), str(count_error), str(executing_time)))
def get_android_params_path(finish_path, bundle): app_params = "AppParams.java" path = str(bundle).replace(".", "/") path = merge(finish_path, "/app/src/main/java", path, "app", app_params) logging.info("Params " + path) return path
def __init__(self, application, params, is_new: bool): # Entity if not is_new: self.application: DriverApplication = application else: self.application: DriverApplicationNew = application self.is_new = is_new # Build params self.need_build = validate_field( params[build_params_scheme.id_need_build]) self.need_clear = validate_field( params[build_params_scheme.id_need_clear]) self.create_app = validate_field( params[build_params_scheme.id_create_app]) self.version_name = validate_field( params[build_params_scheme.id_version_name]) self.version_code = validate_field( params[build_params_scheme.id_version_code]) self.bundle = validate_field(params[build_params_scheme.id_def_bundle]) self.email = validate_field(params[build_params_scheme.id_email]) # Build paths self.finish_path = self.get_final_path(application.bundle, is_new) self.params_path = self.get_android_params_path( self.finish_path, application.bundle, is_new) self.res_path = merge(config.RES_PATH, application.bundle) self.new_bundle = application.bundle
def driver_app_info(app_id: int): # Init variables country_path = merge(config.ASSETS_PATH, 'phonecodes.json') try: # Variables for database app_db = DriverApplicationRepository(config.DATA_URL) # Get application from DB application = app_db.get_app_by_id(app_id) print(application.app_name) res_man = ResourceManager(config.RES_PATH, config.TEMP_PATH) res_saved = res_man.validate_resources( application.bundle, with_remote=False) # TODO with remote True) print(res_saved) # Read countries list with open(country_path) as data_file: countries = json.load(data_file) except Exception as e: traceback.print_exc() error_response = BaseError.generate_base_error(data=e.args) logging.error(error_response) # Render View return error_response response: Response = make_response( render_template("driver-app-info.html", app=application, countries=countries, android_driver=res_saved["android_driver"] or False, google_driver=res_saved["google_driver"] or False)) # Render View return response
def update_images(path, static_path): platforms = ["android", "ios"] disk = GoogleDisk(with_auth=True) list_dirs = os.listdir(path) for proj_dir in list_dirs: print(proj_dir) project_path = merge(RES_PATH, proj_dir) image_path = merge(project_path, "android", "logo", "logo-xxhdpi.png") if os.path.exists(image_path): print("copy start") dest_path = merge(static_path, "icon", proj_dir.replace(".", "_") + ".png") shutil.copy(image_path, dest_path) print("copy end")
def replace_ios_bundle(self, bundle, new_bundle): # Begin function work begin_time_replace = time.time() count_total = 0 count_file_replace = 0 count_error = 0 for path, dirs, files in os.walk(self.final_path, True): for cur_name in files: count_total += 1 file_path = merge(path, cur_name) try: text = open(file_path).read() if bundle in text: open(file_path, 'w').write(text.replace(bundle, new_bundle)) count_file_replace += 1 except ValueError: count_error += 1 # End function work end_time_replace = time.time() print("_________________________________________") print("Total inspect file count is " + str(count_total)) print("Total FILE replace count is " + str(count_file_replace)) print("Error count is " + str(count_error)) print("Total time REPLACE is " + str(end_time_replace - begin_time_replace))
def __init__(self, application, theme, params): self.application: Application = application self.theme = theme logging.debug(application) logging.debug(theme) # Build params self.need_build = validate_field( params[build_params_scheme.id_need_build]) self.need_clear = validate_field( params[build_params_scheme.id_need_clear]) self.create_app = validate_field( params[build_params_scheme.id_create_app]) self.version_name = validate_field( params[build_params_scheme.id_version_name]) self.version_code = validate_field( params[build_params_scheme.id_version_code]) self.bundle = validate_field(params[build_params_scheme.id_def_bundle]) self.email = validate_field(params[build_params_scheme.id_email]) self.ios_company_name = validate_field( params[build_params_scheme.ios_company_name]) self.id_build_email = validate_field( params[build_params_scheme.id_build_email]) self.id_company_id = validate_field( params[build_params_scheme.id_company_id]) # Build paths self.finish_path = self.get_final_path(application.bundle_ios) self.params_path = self.get_ios_params_path(self.finish_path) self.constants_path = self.get_ios_constant_path(self.finish_path) self.launch_screen_path = self.get_ios_launch_path(self.finish_path) self.res_path = merge(config.RES_PATH, application.bundle) self.country = am.get_country(application.country) self.new_bundle = application.bundle_ios
def create_ios_provision(self, output_path): prod = "Prod" dev = "Dev" app_store = "AppStore" provision = ".mobileprovision" script_path = merge(self.assets_path, '/create_provisions.sh') params = os.environ if not os.path.exists(output_path): os.makedirs(output_path) params[IosBuildEnv.BUNDLE] = self.application.bundle_ios params[IosBuildEnv.APPLE_ID] = self.apple_id params[IosBuildEnv.TEAM_NAME] = self.team_name params[IosBuildEnv.PLATFORM] = "ios" params[IosBuildEnv.OUTPUT_PATH] = output_path params[IosBuildEnv.PROVISION_NAME_PROD] = self.application.bundle_ios + prod params[IosBuildEnv.OUTPUT_NAME_PROD] = self.application.bundle_ios + prod + provision params[IosBuildEnv.PROVISION_NAME_DEV] = self.application.bundle_ios + dev params[IosBuildEnv.OUTPUT_NAME_DEV] = self.application.bundle_ios + dev + provision params[IosBuildEnv.PROVISION_NAME_APPSTORE] = self.application.bundle_ios + app_store params[IosBuildEnv.OUTPUT_NAME_APPSTORE] = self.application.bundle_ios + app_store + provision subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script
def app_update(): if request.method == api.post: # Init Resource Manager res_man = ResourceManager(config.RES_PATH, config.TEMP_PATH) try: app_helper.validate_app_fields(request.form, check_id=True) parsed_theme = theme_helper.get_theme_from_data(request.form) theme_helper.validate_theme_fields(parsed_theme) index = request.form[app_helper.FIELD_ID] except BaseError as e: traceback.print_exc() error_response = e.generate_error() logging.error(error_response) return error_response except Exception as e: traceback.print_exc() error_response = BaseError.generate_base_error(data=e.args) logging.error(msg=error_response) return error_response try: # Variables for database app_db = ApplicationRepository(config.DATA_URL) theme_db = theme_rep.ThemeRepository(config.DATA_URL) # Theme theme = theme_helper.parse_theme( sort_dict(parsed_theme)) # Dict -> Sort dict -> Theme # Application old_app = app_db.get_app_by_id(index) # App from index old_bundle = old_app.bundle # old sku result = app_helper.generate_app_json(request.form, theme.hash) # Form -> JSON application = app_helper.parse_app_by_json(result) # JSON -> App application.id = index # Commit DB app_db.update_app(application) # Update app in DB theme_db.update_theme(theme) # Update theme in DB except Exception as e: return DataBaseError(subcode=DataBaseError.duplicate_code, data=e.args).generate_error() try: res_man.update_app_res(request.files, old_bundle, application.bundle) # Update Res ResourceManager.create_app_icon(request.files, config.STATIC_PATH, application.bundle) return redirect(merge(api.get_app_info_num, index)) except BaseError as e: traceback.print_exc() error_response = e.generate_error() logging.error(error_response) return error_response return redirect(api.get_app_list)
def get_country(code: str) -> dict: country_assets = merge(config.ASSETS_PATH, 'phonecodes.json') with open(country_assets) as data_file: countries = json.load(data_file) for country in countries: if country['cc'] == code.upper(): return country
def generate_local(final_path, sdk_path): sdk = "sdk.dir" local = "/local.properties" equal = "=" file = open(merge(final_path, local), 'w+') file.writelines([sdk + equal + sdk_path, "\n"]) file.close()
def create(res_path: str, name: str) -> None: src = merge(res_path, name) if os.path.exists(src): raise PathError(subcode=PathError.path_exist, data=PathError.path_exist_mes % src) os.makedirs(src)
def get_android_params_path(finish_path, bundle, is_new: bool): app_params = "AppParams.java" param_folder = "data" if is_new else "helper" path = str(bundle).replace(".", "/") path = merge(finish_path, "/app/src/main/java", path, param_folder, app_params) logging.info("Params " + path) return path
def __create_logo_content(self, name): itunnes = "itunesartwork@2x" scale = "scale" images = "images" filename = "filename" idiom = "idiom" size = "size" IPHONE_SCALES = {"2x": "@2", "3x": "@3"} IPHONE_SIZES = ["20x20", "29x29", "40x40", "60x60"] IPOD_SCALES = {"1x": "@1", "2x": "@2"} IPOD_SIZES = ["20x20", "29x29", "40x40", "60x60", "76x76", "83.5x83.5"] content_path = merge(self.assets_path, CONTENT_APP) with open(content_path) as data_file: content_json = json.load(data_file) # TODO # TODO GOVNOCODE for image in content_json[images]: if image[idiom] == idiom_iphone: for iphone_size in IPHONE_SIZES: if iphone_size == image[size]: for scale_key in IPHONE_SCALES.keys(): if image[scale] == scale_key: # [email protected] image[ filename] = name + "-" + idiom_iphone + iphone_size + IPHONE_SCALES[ scale_key] + png if image[idiom] == idiom_ipad: for ipod_size in IPOD_SIZES: if ipod_size == image[size]: for scale_key in IPOD_SCALES.keys(): if image[scale] == scale_key: # [email protected] image[ filename] = name + "-" + idiom_ipad + ipod_size + IPOD_SCALES[ scale_key] + png file = open( merge(self.finish_path, RES_PATH, name + appiconset, CONTENT), 'w+') file.write(json.dumps(content_json)) file.close()
def _build_app(self, ios_builder): ios_builder.create_ios_app() ios_builder.create_ios_dev(output_path=merge(self.res_path, "/cert")) ios_builder.create_ios_cert("3colors", self.res_path) ios_builder.create_ios_provision( output_path=merge(self.res_path, "/provision")) ios_builder.replace_ios_provision(file_path=merge( self.finish_path, '/Client.xcodeproj/project.pbxproj')) ios_builder.replace_distribution_cert(file_path=merge( self.finish_path, '/Client.xcodeproj/project.pbxproj'), company_id=self.id_company_id) ios_builder.build_ios_app(workspace_path=merge(self.finish_path, "/Client.xcworkspace"), output_path=config.TEMP_PATH, name=self.application.app_sku + ".ipa") ios_builder.upload_ios_app(ipa_path=merge( config.TEMP_PATH, self.application.app_sku + ".ipa"), app_version=self.version_code, build_number=self.version_name) logging.debug("Start sending certificate") path_to_cert = merge(self.res_path, self.application.bundle_ios + ".p12") if os.path.exists(path_to_cert): self.__send_push_cert(self.email, path_to_cert) logging.debug("End sending certificate")
def replace_logo(self): logo = "appicon" itunnes = "itunesartwork@2x" IDIOMS = ["iphone", "ipad"] idiom_iphone = "iphone" IPHONE_SCALES = ["@2", "@3"] IPHONE_SIZES = ["20x20", "29x29", "40x40", "60x60"] idiom_ipad = "ipad" IPAD_SIZES = ["20x20", "29x29", "40x40", "76x76", "83.5x83.5"] # TODO IPAD_SCALES = ["@1", "@2"] self.remove_images_content( merge(self.finish_path, RES_PATH, logo + appiconset)) # TODO GOVNOCODE for idiom in IDIOMS: if idiom == idiom_iphone: for size in IPHONE_SIZES: for scale in IPHONE_SCALES: shutil.copy( src=merge( self.path_to_res, res_type, logo, logo + "-" + idiom_iphone + size + scale + png), # TODO dst=merge( self.finish_path, RES_PATH, logo + appiconset, logo + "-" + idiom_iphone + size + scale + png)) if idiom == idiom_ipad: for size in IPAD_SIZES: for scale in IPAD_SCALES: shutil.copy( src=merge( self.path_to_res, res_type, logo, logo + "-" + idiom_ipad + size + scale + png), # TODO dst=merge( self.finish_path, RES_PATH, logo + appiconset, logo + "-" + idiom_ipad + size + scale + png)) self.__create_logo_content(logo)
def get_app_info(app_id: int): # Init variables country_path = merge(config.ASSETS_PATH, 'phonecodes.json') try: # Variables for database app_db = ApplicationRepository(config.DATA_URL) theme_db = theme_rep.ThemeRepository(config.DATA_URL) # Get application from DB application = app_db.get_app_by_id(app_id) # Get theme from DB theme = theme_db.get_theme_by_hash(application.theme) theme_dict = sort_dict(theme.dict()) # Theme to dict # Remove in further del theme_dict['id'] del theme_dict['hash'] # Generate double quotes theme_dict = json.dumps(theme_dict) logging.info("Theme for " + application.app_name.upper() + " | " + theme_dict) res_man = ResourceManager(config.RES_PATH, config.TEMP_PATH) res_saved = res_man.validate_resources(application.bundle, with_remote=False) # TODO with remote True path = AndroidLauncher.get_final_path(application.bundle) # TODO from this is_android_existing = os.path.exists(path) path = IosLauncher.get_final_path(application.bundle_ios) is_ios_existing = os.path.exists(path) # Read countries list with open(country_path) as data_file: countries = json.load(data_file) except Exception as e: traceback.print_exc() error_response = BaseError.generate_base_error(data=e.args) logging.error(error_response) # Render View return error_response response: Response = make_response(render_template("app-info.html", app=application, colors=theme_dict, countries=countries, android_res=res_saved["android"] or False, ios_res=res_saved["ios"] or False, google_res=res_saved["google"] or False)) response.set_cookie("is_android_existing", str(is_android_existing or False)) response.set_cookie("is_ios_existing", str(is_ios_existing or False)) # Render View return response
def generate_pods(src: str, assets_path: str) -> None: path = "MASTER_PATH" script_path = merge(assets_path, '/cocoa_install.sh') params = os.environ params[path] = src # Put path to final project in variables environment print(script_path) # TODO REPLACE ON os.chmode subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script
def __create_set_content(self, name): scale = "scale" images = "images" filename = "filename" content = "Contents.json" SCALES = {"2x": "@2", "3x": "@3"} content_path = merge(self.assets_path, content) with open(content_path) as data_file: content_json = json.load(data_file) for image in content_json[images]: for scale_key in SCALES.keys(): if image[scale] == scale_key: image[filename] = name + SCALES[scale_key] + png file = open( merge(self.finish_path, RES_PATH, name + imageset, content), 'w+') file.write(json.dumps(content_json)) file.close()
def create_ios_dev(self, output_path): script_path = merge(self.assets_path, '/create_dev.sh') params = os.environ params[IosBuildEnv.APPLE_ID] = self.apple_id params[IosBuildEnv.TEAM_NAME] = self.team_name params[IosBuildEnv.PLATFORM] = "ios" params[IosBuildEnv.OUTPUT_PATH] = output_path subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script
def remote_validate_type(name: str, res_type: str, save_path: str, with_save: bool = False) -> bool: ANDROID = "android" IOS = "ios" GOOGLE = "google" from std.disk.google_disk import GoogleDisk drive = GoogleDisk(with_auth=True) if res_type == ANDROID or res_type == IOS: res_name = parse_sku(name) + "-" + res_type + ".zip" elif res_type == GOOGLE: res_name = "google-services.json" else: raise DataEror(subcode=DataError.not_found, data=DataError.not_found_mes % name) print("remote_validate_type before %s" % res_name) is_exist = drive.check(res_name, drive.get_folder_id_by_name(name)) print("remote_validate_type after %s" % is_exist) if not is_exist or not with_save: return is_exist elif is_exist and with_save: print("remote_validate_type is_exist") save_path = merge(save_path, res_type) if not os.path.exists(save_path): os.makedirs(save_path) save_file_path = merge(save_path, res_name) drive.load_file(res_name, save_file_path, drive.get_folder_id_by_name(name)) if allowed_zip(res_name): print("remote_validate_type allowed_zip") print("remote_validate_type %s" % save_path) zip_ref = zipfile.ZipFile(save_file_path, 'r') zip_ref.extractall(save_path) zip_ref.close() os.remove(save_file_path) return True
def create_ios_cert(self, password, output_path): script_path = merge(self.assets_path, '/create_cert.sh') params = os.environ params[IosBuildEnv.BUNDLE] = self.application.bundle_ios params[IosBuildEnv.CERT_PASS] = password params[IosBuildEnv.CERT_FILE_NAME] = self.application.bundle_ios + ".pem" params[IosBuildEnv.TEAM_NAME] = self.team_name params[IosBuildEnv.OUTPUT_PATH] = output_path subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script
def build_ios_app(self, workspace_path, output_path, name): script_path = merge(self.assets_path, '/build.sh') params = os.environ params[IosBuildEnv.WORKSPACE_PATH] = workspace_path print(params[IosBuildEnv.WORKSPACE_PATH]) params[IosBuildEnv.BUILD_SCHEME] = "Client" params[IosBuildEnv.OUTPUT_PATH] = output_path params[IosBuildEnv.OUTPUT_NAME] = name subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script
def post_build_status(base_url: str, app_index: int, status: int, build_type: str) -> None: data = {"app_index": app_index, "status": status, "time": time.time()} route: str if build_type == LauncherFactory.BUILD_IOS or build_type == LauncherFactory.BUILD_ANDROID: route = api.post_update_build_status elif build_type == LauncherFactory.BUILD_DRIVER: route = api.post_driver_update_build_status elif build_type == LauncherFactory.BUILD_DRIVER_NEW: route = api.post_driver_new_update_build_status requests.post(url=merge(base_url + route), data=data)
def _prepare_res(self, res_helper): logo_splash = "logo_splash" menulogo = "menulogo" res_helper.replace_launch_image(logo_splash) res_helper.replace_image_set(menulogo) res_helper.replace_logo() del self.theme["id"] res_helper.put_color_scheme( merge(self.finish_path, "/Client/Helpers/Colors.swift"), json.dumps(self.theme)) res_helper.replace_colors(screen_path=self.launch_screen_path, splash_color=self.theme["splash_bg"]) res_helper.replace_project_name(self.application.app_name)
def upload_ios_app(self, ipa_path, app_version, build_number): script_path = merge(self.assets_path, '/upload.sh') params = os.environ params[IosBuildEnv.APPLE_ID] = self.apple_id params[IosBuildEnv.BUNDLE] = self.application.bundle_ios params[IosBuildEnv.IPA_PATH] = ipa_path params[IosBuildEnv.TEAM_NAME] = self.team_name params[IosBuildEnv.APP_VERSION] = app_version params[IosBuildEnv.BUILD_NUMBER] = build_number print(params) subprocess.call(["chmod +x " + script_path], shell=True, env=params) # Get permissions for run script subprocess.call([script_path], shell=True, env=params) # Run script