From 848d16c5e9214c9184bf51dd4cb0145789b65d95 Mon Sep 17 00:00:00 2001 From: ckamte Date: Mon, 5 Jan 2026 10:11:33 +0630 Subject: [PATCH] update script to version 1.2 --- CHANGELOG.md | 11 + ccdl-win.py | 1533 ++++++++++++++++++++----------------- suite_installer/Readme.md | 6 +- 3 files changed, 854 insertions(+), 696 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..08a29b8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +## version 1.2 +1. Add Suite builder. +2. Change code styles +3. Add multiple language option. +4. Some minor improvements. + +## version 1.1 +1. Add batch download. + +## version 1.0 +Convert and modified from https://github.com/Drovosek01/adobe-packager \ No newline at end of file diff --git a/ccdl-win.py b/ccdl-win.py index 8216982..839b4d1 100644 --- a/ccdl-win.py +++ b/ccdl-win.py @@ -7,6 +7,7 @@ Based on https://github.com/Drovosek01/adobe-packager """ import os +import io import string import random import argparse @@ -15,6 +16,7 @@ import locale import ctypes import sys import operator +from pathlib import Path from collections import OrderedDict from xml.etree import ElementTree as ET @@ -36,12 +38,12 @@ except ImportError: or run: pip3 install tqdm.""" ) -SCRIPT_NAME = "Adobe CC Packages Downloader for Windows" -VERSION = 1 -VERSION_STR = "1.1.0" + +SCRIPT_NAME = "Adobe CC Packages Downloader For Windows" +VERSION_STR = "1.2.1" CODE_QUALITY = "Really_AWFUL" -ADOBE_PRODUCTS_XML_URL = "https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v{urlVersion}/products/all?channel=ccm&channel=sti&platform={installPlatform}&productType=Desktop&_type=xml" +ADOBE_PRODUCTS_XML_URL = "https://prod-rel-ffc-ccm.oobesaas.adobe.com/adobe-ffc-external/core/v{urlVersion}/products/all?channel=ccm&channel=sti&platform={reqPlatforms}&productType=Desktop&_type=xml" ADOBE_APPLICATION_JSON_URL = "https://cdn-ffc.oobesaas.adobe.com/core/v3/applications" ADOBE_REQ_HEADERS = { @@ -59,18 +61,19 @@ ADOBE_DL_HEADERS = {"User-Agent": "Creative Cloud"} session = requests.sessions.Session() -def show_version(name, version, p=4, c="=") -> None: - """Show script title""" - tl = len(name) + (p * 2) - print(c * tl) - print(c + name.center(tl - 2) + c) - print(f"{version.center(tl, c)}\n") - +def show_info(name: str, version: str, pad: int, bdr: str) -> None: + """Show script information""" + tl = len(name) + (pad * 2) + print(bdr * tl) + print(bdr + name.center(tl - 2) + bdr) + print(version.center(tl, bdr)) -def get_arguments(): + +def get_arguments() -> argparse.Namespace: + """Get command-line parameters""" parser = argparse.ArgumentParser() parser.add_argument( - "-l", "--installLanguage", help="Language code (eg. en_US)", action="store" + "-l", "--installLanguage", help="Language code (eg. en_US). For more than one language us comma to separate languages", action="store" ) parser.add_argument( "-o", "--osLanguage", help="OS Language code (eg. en_US)", action="store" @@ -129,10 +132,6 @@ def get_arguments(): return parser.parse_args() -def get_install_dir(): - return os.path.join(os.environ["PROGRAMFILES"], "Adobe") - - def questiony(question: str) -> bool: """Question prompt default Y.""" reply = None @@ -141,17 +140,25 @@ def questiony(question: str) -> bool: return reply in ("", "y") -def url_version(): +def get_winver() -> str: + winVer = sys.getwindowsversion() + return "{}.{}.{}".format(winVer.major, winVer.minor, winVer.build) + + +def set_url_version(args: argparse.Namespace) -> str: + """Set url version for downloading ffc.xml""" urlVersion = None acceptVers = ["v4", "v4", "v6", "4", "5", "6"] + if args.urlVersion: if args.urlVersion.lower() in acceptVers: urlVersion = args.urlVersion[-1] print(f"\nUsing provided url version: {urlVersion}") else: - urlVersion = None print( - f'Invalid URL Version [{args.urlVersion}]! Please select from version list below\n') + f'Invalid argument "{args.urlVersion}" for URL version! Please select from version list below\n' + ) + urlVersion = None while not urlVersion: versions = { @@ -163,21 +170,22 @@ def url_version(): for p, v in versions.items(): print("[{}]{}{}".format(p, (12 - len(p)) * " ", v)) - val = ( + usrInput = ( input( - "\nPlease enter the URL version(v4/v5/v6) for downloading products.xml, or nothing for v6: " + "\nPlease enter the URL version(v4/v5/v6), or nothing for v6: " ) or "v6" ) - if val in acceptVers: - urlVersion = val[-1] + if usrInput in acceptVers: + urlVersion = usrInput[-1] else: - print(f"Invalid URL version: {val}\n") + print(f"Invalid URL version: {usrInput}") return urlVersion -def app_platform(): +def set_app_platform(args: argparse.Namespace) -> str: + """Set application platform""" winPlatforms = { "win32": "32 Bit Windows", "win64": "64 Bit Windows", @@ -187,10 +195,11 @@ def app_platform(): if args.appPlatform: if args.appPlatform in winPlatforms: appPlatform = args.appPlatform - print(f"\nUsing provided version {appPlatform}: ") + print(f"\nUsing provided windows platform: {appPlatform}") else: print( - f'Invalid application platform {args.appPlatform}! Please select form list below\n') + f"Invalid windows platform [{args.appPlatform}]! Please select form list below\n" + ) appPlatform = None while not appPlatform: @@ -212,184 +221,137 @@ def app_platform(): return appPlatform -def select_product(products, sapCodes): - for s, d in sapCodes.items(): - print("[{}]{}{}".format(s, (10 - len(s)) * " ", d)) - - slectedProduct = None - - while slectedProduct is None: - val = input( - "\nPlease enter the SAP Code of the desired product from the list above: " - ).upper() - if products.get(val): - slectedProduct = val - elif val == "": - print("No product selected! Please use a value from the list above.") - else: - print(f"{val} is not available! Please use a value from the list above.") - return slectedProduct - - -def product_code(products, sapCodes): - codeList = [] - toDown = args.sapCode - # for batch download - if toDown: - toDown = toDown.upper().split(',') - for prodToDown in toDown: - if prodToDown in sapCodes: - print(f"\nAdd {prodToDown} to download list") - codeList.append(prodToDown) - - else: - print(f"\n{prodToDown} is not available!\n") - answer = None - while answer is None: - answer = input("Are you want to continue? (y/n): ") - if answer.lower() in ["y", "yes"]: - answer = select_product(products, sapCodes) - # for duplicate entry - while answer in codeList: - print( - f"\nAdd {answer} already exist in donload list") - answer = input( - "\nPlease enter the SAP Code of the desired product from the list above: " - ).upper() - else: - print(f"\nAdd {answer} to download list") - codeList.append(answer) - elif answer.lower() in ["n", "no"]: - print("\nProgram terminated!\n") - else: - print("\nPlease enter yes or no!") - answer = None - - else: - toDown = select_product(products, sapCodes) - codeList.append(toDown) - - if len(codeList) > 1: - print(f"\nThe latest version of products will download") - - return codeList - - -def get_last_version(versions): - last = None - for v in reversed(versions.values()): - if v["buildGuid"] is not None or v["manifestURL"] is not None: - last = v["productVersion"] - else: - print("\nCannot determine latest version!\n") - return last - - -def product_version(product, versions): - version = None - if args.version: - if versions.get(args.version): - print(f"\nUsing provided version: {args.version}") - version = args.version - else: - print(f"\nProvided version not found: {args.version}") - - if not version: - lastVersion = get_last_version(versions) - - print("\nAvailable versions list") - for v in reversed(versions.values()): - if v["buildGuid"] is not None or v["manifestURL"] is not None: - print( - "{} Platform: {} - {}".format( - product["displayName"], v["appPlatform"], v["productVersion"] - ) - ) - - while version is None: - val = ( - input( - f"\nPlease enter the desired version. Nothing for {lastVersion}:") - or lastVersion - ) - if versions.get(val): - version = val - else: - print( - f"{val} is not a valid version. Please use a value from the list above.") +def set_config() -> dict: + """Set configuration data from arguments""" + # get arguments + args = get_arguments() + reqUrlVer = set_url_version(args) + reqAppPlatform = set_app_platform(args) print( - "\nPrepare to download Adobe {}, version {}".format( - product["displayName"], version - ) - ) - return version + f"\nPrepare to download {reqAppPlatform} products form url version {reqUrlVer}") + if args.Auth: + ADOBE_REQ_HEADERS["Authorization"] = args.Auth -def install_language(supportedLangs): - if "mul" in supportedLangs: - supportedLangs[supportedLangs.index("mul")] = "All" + allowedPlatforms = [reqAppPlatform] + urlPlatforms = reqAppPlatform + if reqAppPlatform == "win64": + allowedPlatforms.append("win32") + urlPlatforms += ",win32" + + # destination dir + if args.destination: + print(f"\nUsing provided destination: {args.destination}") + dest = args.destination else: - if "All" not in supportedLangs: - supportedLangs.append("All") - supportedLangs.sort() + dest = os.path.dirname(os.path.realpath(__name__)) - # Detecting current language. - windll = ctypes.windll.kernel32 - osLang = locale.windows_locale[windll.GetUserDefaultUILanguage()] + # create products directory + prodDir = os.path.join(dest, "products") + os.makedirs(prodDir, exist_ok=True) - if args.osLanguage: - osLang = args.osLanguage + winver = get_winver() + print(f"\nSet windows version to {winver}. You may not install or run products on Windows version below: {winver}!") - defLang = "All" - if osLang in supportedLangs: - defLang = osLang + print(f"\nDownloaded files will be saved in: {prodDir}") - installLanguage = None - if args.installLanguage: - if args.installLanguage in supportedLangs: - print(f"\nUsing provided language: {args.installLanguage}") - installLanguage = args.installLanguage - else: - print(f"\nProvided language not available: {args.installLanguage}") - - if not installLanguage: - print("\nAvailable languages: {}".format(", ".join(supportedLangs))) - while installLanguage is None: - val = ( - input( - f"\nPlease enter the desired install language, or nothing for [{defLang}]: " - ) - or defLang - ) - if len(val) == 5: - val = val[0:2].lower() + val[2] + val[3:5].upper() - elif len(val) == 3: - val = val[0].upper() + val[1:].lower() - if val in supportedLangs: - installLanguage = val - else: - print( - f"{val} is not available. Please use a value from the list above.") - - if osLang != installLanguage: - if installLanguage != "All": - while osLang not in supportedLangs: - print("Could not detect your default Language.") - osLang = ( - input( - f"\nPlease enter the your OS Language, or nothing for [{installLanguage}]: " - ) - or installLanguage - ) - if osLang not in supportedLangs: - print( - f"{osLang} is not available. Please use a value from the list above.") - - return installLanguage + return { + "reqUrlVer": reqUrlVer, + 'urlPlatforms': urlPlatforms, + "reqAppPlatform": reqAppPlatform, + "allowedPlatforms": allowedPlatforms, + "downIcons": args.productIcons, + "noRepeat": args.noRepeatPrompt, + "osLang": args.osLanguage, + "reqLang": args.installLanguage, + "toDown": args.sapCode, + "reqVer": args.version, + "productDir": prodDir, + "skip": args.skipExisting, + "osVersion": winver + } -def product_icons(elem): +def create_xml(name: str, data) -> None: + """Write data to xml file""" + with open(name, "wb+") as f: + f.write(data) + + +def create_json(name: str, data) -> None: + """Write data to json file""" + with open(name, "w") as f: + json.dump(data, f) + + +def append_file(name: str, data: str | None) -> None: + """Append data to existing file""" + with open(name, "a+", encoding='utf-8') as f: + if data is not None: + f.write(data + "\n") + + +def download_data(url: str, header: dict) -> bytes: + """Get raw data""" + try: + response = session.get(url, stream=True, headers=header) + response.encoding = "utf-8" + response.raise_for_status() + + total_size = int(response.headers.get("content-length", 0)) + chunk_size = 1024 # 1 KB chunks + mem_file = io.BytesIO() + with tqdm(total=total_size or None, unit="B", unit_scale=True, unit_divisor=1024) as pbar: + for chunk in response.iter_content(chunk_size=chunk_size): + mem_file.write(chunk) + pbar.update(len(chunk)) + + downData = mem_file.getvalue() + mem_file.close() + + except requests.exceptions.HTTPError as err_h: + print(f"Connection error occurred: {err_h}") + + except requests.exceptions.RequestException as err_r: + print(f"Unexpected error occurred: {err_r}") + + else: + return downData + + # exit on download error + sys.exit("\nCannot download data!") + + +def download_json(url: str, header: dict, file: str | None = None) -> dict: + """Download json data(use filename for testing)""" + if file and Path(file).is_file(): + with open(file, "r") as f: + return json.load(f) + + jsonData = download_data(url, header) + + if file: + create_json(file, json.loads(jsonData.decode('utf-8'))) + + return json.loads(jsonData.decode('utf-8')) + + +def download_xml(url: str, header: dict, file=None) -> ET.ElementTree: + """Download xml data(use filename for testing)""" + if file and Path(file).is_file(): + return ET.parse(file) + + xmlData = download_data(url, header) + + if file: + create_xml(file, xmlData) + + return ET.fromstring(xmlData) + + +def product_icons(elem: dict) -> list[str]: + """Get icons for product""" productIcons = [] if len(elem.find("productIcons")): for icon in elem.findall("productIcons/icon"): @@ -397,7 +359,8 @@ def product_icons(elem): return productIcons -def product_languages(elem): +def product_languages(elem: dict) -> list[str]: + """Get supported language for product""" supportedLang = [] if len(elem.find("locales")): for locale in elem.findall("locales/locale"): @@ -405,21 +368,22 @@ def product_languages(elem): return supportedLang -def parse_products_xml(products_url, url_version, allowed_platform, selected_platform): - # get xml data - print("Downloading product data\n") - response = session.get(products_url, stream=True, - headers=ADOBE_REQ_HEADERS) - response.encoding = "utf-8" - products_xml = ET.fromstring(response.content) +def get_products(cfg: dict) -> dict: + """Get all product and dependencies list""" + # get products.xml + products_xml_url = ADOBE_PRODUCTS_XML_URL.format( + urlVersion=cfg["reqUrlVer"], reqPlatforms=cfg["urlPlatforms"] + ) - # with open("ffc.xml", "wb+") as f: - # f.write(response.content) - # products_xml = ET.parse("ffc.xml") + print("\nDownloading all available products...") + productXml = download_xml(products_xml_url, ADOBE_REQ_HEADERS) - cdn = products_xml.find(".//*/cdn/secure").text + # add cdn address to config + cfg['cdn'] = productXml.find(".//*/cdn/secure").text + + # parse xml data allProducts = {} - for channel in products_xml.findall(".//channel"): + for channel in productXml.findall(".//channel"): appType = "dep" if channel.attrib["name"] == "ccm": appType = "app" @@ -430,11 +394,11 @@ def parse_products_xml(products_url, url_version, allowed_platform, selected_pla for plat in [ item for item in product.findall("./platforms/platform") - if item.attrib["id"] in allowed_platform + if item.attrib["id"] in cfg["allowedPlatforms"] ]: appPlatform = plat.attrib["id"] # platform filter for main app - if appType == "app" and appPlatform != selected_platform: + if appType == "app" and appPlatform != cfg["reqAppPlatform"]: continue if plat.findall( @@ -473,137 +437,677 @@ def parse_products_xml(products_url, url_version, allowed_platform, selected_pla "buildGuid": languageSet.get("buildGuid"), "manifestURL": manifestURL, } - if args.productIcons: + if cfg["downIcons"]: allProducts[sapCode]["versions"][productVersion]['productIcons'] = product_icons( product) else: - if url_version >= 5: + if int(cfg["reqUrlVer"]) >= 5: allProducts.pop(sapCode, None) - return allProducts, cdn + return allProducts -def get_products(): - selectedVersion = url_version() - print(f"\nUsing URL version {selectedVersion}\n") +def select_product(allProducts: dict) -> str: + """Select a product to down""" + selectedProduct = None + while selectedProduct is None: + show_avail_products(allProducts) + val = input( + "\nPlease enter SAP Code for desired product: " + ).upper() + if allProducts.get(val): + selectedProduct = val + else: + v = val or "empty" + print( + f"[{v}] is not available! Please use a value from the list below." + ) + return selectedProduct - selectedPlatform = app_platform() - print(f"\nGetting {selectedPlatform} products\n") - if args.Auth: - ADOBE_REQ_HEADERS["Authorization"] = args.Auth +def get_last_version(versions: dict) -> str: + """Ge last version of selected product""" + last = None + for v in reversed(versions.values()): + if v["buildGuid"] is not None or v["manifestURL"] is not None: + last = v["productVersion"] + else: + print("\nCannot determine latest version!\n") + return last - allowedPlatforms = [selectedPlatform] - productsPlatform = selectedPlatform - if selectedPlatform == "win64": - allowedPlatforms.append("win32") - productsPlatform += ",win32" - products_xml_url = ADOBE_PRODUCTS_XML_URL.format( - urlVersion=selectedVersion, installPlatform=productsPlatform - ) - # download and parse product xml - products, cdn = parse_products_xml( - products_xml_url, selectedVersion, allowedPlatforms, selectedPlatform - ) - - sapCodes = {} - for p in products.values(): +def show_avail_products(allProducts: dict) -> None: + """Show available products list""" + availCodes = {} + for p in allProducts.values(): if p["appType"] == "app": versions = p["versions"] - lastVersion = get_last_version(versions) - if lastVersion: - sapCodes[p["sapCode"]] = p["displayName"] - print(f"{str(len(sapCodes))} products found:") + if get_last_version(versions): + availCodes[p["sapCode"]] = p["displayName"] + # print(f"{str(len(availCodes))} products found.") - return products, cdn, sapCodes, selectedPlatform + print("\n" + ("-" * 40)) + print("Available products and codes") + print("-" * 40) + for s, d in availCodes.items(): + print("[{}]{}{}".format(s, (10 - len(s)) * " ", d)) -def get_download_path(): - """Ask for desired download folder""" - if args.destination: - print(f"\nUsing provided destination: {args.destination}\n") - dest = args.destination +def download_list(allProducts: dict) -> list[str]: + """Create products to download list""" + codeList = [] + toDown = cfg["toDown"] + # for batch download + if toDown: + toDown = toDown.upper().split(',') + for prodToDown in toDown: + if prodToDown in allProducts: + print(f"\nAdd {prodToDown} to download list") + codeList.append(prodToDown) + + else: + print(f"\n{prodToDown} is not available!\n") + answer = None + while answer is None: + answer = input("Are you want to continue? (y/n): ") + if answer.lower() in ["y", "yes"]: + answer = select_product(allProducts) + # for duplicate entry + while answer in codeList: + print( + f"\nAdd [{answer}] already exist in download list") + answer = input( + "\nPlease enter the SAP Code of the desired product from the list above: " + ).upper() + else: + print(f"\nAdd [{answer}] to download list") + codeList.append(answer) + elif answer.lower() in ["n", "no"]: + print("\nBye!") + sys.exit() + else: + print("\nPlease enter yes or no!") + answer = None + else: - dest = os.path.dirname(os.path.realpath(__name__)) - return dest + toDown = select_product(allProducts) + codeList.append(toDown) + + return codeList -def download_progress(url, dest_dir, prefix=""): - # get file size - response = session.head(url, stream=False, headers=ADOBE_DL_HEADERS) - total_size_in_bytes = int(response.headers.get("content-length", 0)) +def select_app_version(product: dict, batch: bool) -> str: + """Select version for product""" + availVer = product["versions"] + version = None + if batch: + version = get_last_version(availVer) + elif cfg["reqVer"]: + reqVersion = cfg["reqVer"] + if availVer.get(reqVersion): + print(f"\nUsing provided version: {reqVersion}") + version = reqVersion + else: + print(f"\nProvided version not found: {reqVersion}") - # skip existing files + if not version: + lastVersion = None + print("\nAvailable versions list") + for v in reversed(availVer.values()): + if v["buildGuid"] is not None or v["manifestURL"] is not None: + print( + "{} for {} - {}".format( + product["displayName"], v["appPlatform"], v["productVersion"] + ) + ) + lastVersion = v["productVersion"] + + while version is None: + val = ( + input( + f"\nPlease enter the desired version. Nothing for [{lastVersion}]:" + ) + or lastVersion + ) + if availVer.get(val): + version = val + else: + print( + f"{val} is not a valid version. Please use a value from the list above." + ) + + print( + "\nPrepare to download Adobe {}, version {}".format( + product["displayName"], version + ) + ) + + return availVer[version] + + +def select_language(appLangs: list, defLang: str) -> str: + """Select language for product""" + print("\nAvailable languages: {}".format(", ".join(appLangs))) + selLang = None + while selLang is None: + val = ( + input( + f"\nPlease enter the desired install language, or nothing for [{defLang}]: " + ) + or defLang + ) + if len(val) == 5: + val = val[0:2].lower() + val[2] + val[3:5].upper() + + if val in appLangs: + selLang = val + else: + print( + f"{val} is not available. Please use a value from the list above." + ) + + if selLang.lower() == "all": + selLang = "mul" + + return selLang + + +def install_language(appLangs: list[str]) -> list[str]: + """Set language for product""" + if "mul" in appLangs: + appLangs[appLangs.index("mul")] = "all" + else: + if "all" not in appLangs: + appLangs.append("all") + appLangs.sort() + + osLang = cfg["osLang"] + if osLang is None: + # Detecting current language. + windll = ctypes.windll.kernel32 + osLang = locale.windows_locale[windll.GetUserDefaultUILanguage()] + + # if os language in supported languages + defLang = "all" + if osLang in appLangs: + defLang = osLang + + installLanguage = [] + if cfg["reqLang"]: + # all means all + if "all" in cfg["reqLang"]: + cfg["reqLang"] = "all" + + reqLangs = cfg["reqLang"].split(",") + for l in reqLangs: + if l in appLangs: + print(f"\nAdding provided language: {l}") + installLanguage.append(l) + else: + print(f"\nProvided language not available: {l}") + if questiony("\nDo you want to select another language?"): + newLang = select_language(appLangs, defLang) + # all (mul) means all languages + if newLang == "mul" or newLang == "all": + installLanguage = ["mul"] + break + + while newLang in installLanguage: + print(f"\n{newLang} already exist in your list!") + newLang = select_language(appLangs, defLang) + + installLanguage.append(newLang) + + if installLanguage == []: + if questiony("\nNo language selected. Do you want to quit?"): + sys.exit("Bye!") + # update configuration + # cfg["reqLang"] = installLanguage + + else: + installLanguage = [select_language(appLangs, defLang)] + + return installLanguage + + +def download_file(url: str, dest: str, prefix=None) -> bool: + """Download package file""" filename = os.path.basename(url) if prefix: filename = prefix + filename - dest_dir = os.path.join(dest_dir, filename) + destDir = os.path.join(dest, filename) - if ( - args.skipExisting - and os.path.isfile(dest_dir) - and os.path.getsize(dest_dir) == total_size_in_bytes - ): - print("Downloaded file is OK, skipping ... \n") - return True + try: + # get file size + response = session.head(url, stream=False, headers=ADOBE_DL_HEADERS) + lengthInBytes = int(response.headers.get("content-length", 0)) - # download file - response = session.get(url, stream=True, headers=ADOBE_REQ_HEADERS) + if ( + cfg["skip"] + and os.path.isfile(destDir) + and os.path.getsize(destDir) == lengthInBytes + ): + print(f"\nDownloaded file seems OK, skipping...") + return True - block_size = 1024 # 1 Kibibyte - progress_bar = tqdm(total=total_size_in_bytes, unit="iB", unit_scale=True) - with open(dest_dir, "wb") as file: - for data in response.iter_content(block_size): - progress_bar.update(len(data)) - file.write(data) + # download file + response = session.get(url, stream=True, headers=ADOBE_REQ_HEADERS) - progress_bar.close() - - if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes: - print("Cannot determine download size!") - return False + blockSize = 1024 # 1 Kilobyte + with tqdm(total=lengthInBytes, unit="iB", unit_scale=True) as pBar: + with open(destDir, "wb") as file: + for data in response.iter_content(blockSize): + pBar.update(len(data)) + file.write(data) + except Exception as e: + print(f"An unexpected error occurred! {e}") else: return True + return False -def icons_download(product, dest_dir): + +def download_icons(prodInfo: list) -> None: """Download product icons""" - print("Downloading product icons\n") + print("\nDownloading product icons...\n") - icon_dir = os.path.join(dest_dir, "icons") - os.makedirs(icon_dir, exist_ok=True) + iconsDir = os.path.join(cfg["productDir"], "icons") + os.makedirs(iconsDir, exist_ok=True) + + icons = prodInfo["productIcons"] + prefix = prodInfo["sapCode"].lower() - icons = product["productIcons"] - prefix = product["sapCode"].lower() for url in icons: - download_progress(url, icon_dir, prefix) + download_file(url, iconsDir, prefix) -def file_download(url, dest_dir, s, v, name=None): +def language_filter(pkgJson: dict | list, language: list) -> dict: + """Stripped out unnecessary data from json file""" + # Source - # https://stackoverflow.com/questions/71543579/python-find-and-replace-all-values-under-a-certain-key-in-a-nested-dictionary + # Posted by flakes + # Retrieved 2025-12-03, License - CC BY-SA 4.0 + if "mul" in language or "all" in language: + return pkgJson + + if isinstance(pkgJson, dict): + key = "Language" + # filter by locale + for k, v in pkgJson.items(): + filtered = None + if k == key: + filtered = [] + for lc in v: + if lc["locale"] in language or lc["locale"] == "mul": + filtered.append(lc) + + # replace with filtered result + pkgJson = { + k: filtered if k == key and v else language_filter(v, language) + for k, v in pkgJson.items() + } + + if isinstance(pkgJson, list): + pkgJson = [language_filter(v, language) for v in pkgJson] + + return pkgJson + + +def do_test(cond: str, key: str | list[str]) -> bool: + """Test condition based on condition strings""" + if "==" in cond: + val = cond.split("==") + opt = operator.eq + elif "!=" in cond: + val = cond.split("!=") + opt = operator.ne + elif "<=" in cond: + val = cond.split("<=") + opt = operator.le + elif ">=" in cond: + val = cond.split(">=") + opt = operator.ge + elif ">" in cond: + val = cond.split(">") + opt = operator.gt + elif "<" in cond: + val = cond.split("<") + opt = operator.lt + else: + return True + + # stripped string + cmp = val[1].strip() + + if "OSVersion" in val[0]: + keys = key.split(".") + cmps = cmp.split(".") + idx = -1 + for c in cmps: + idx = idx + 1 + if (idx > 0): + c = float(f"0.{c}") + k = float(f"0.{keys[idx]}") + else: + c = int(c) + k = int(keys[idx]) + + if opt(k, c) is not True: + return False + + if isinstance(key, list): + return cmp in key + + return opt(key, cmp) + + +def test_and(str: str, osProc: str, osver: str, langs: list[str]) -> bool: + """Check AND (&&) test result""" + conds = str.split("&&") + for c in conds: + if "OSProcessorFamily" in c: + if do_test(c, osProc) is not True: + return False + + if "OSVersion" in c: + if do_test(c, osver) is not True: + return False + + if "installLanguage" in c: + if "all" in langs: + return True + + if do_test(c, langs) is not True: + return False + + return True + + +def test_or(str: str, osProc: str, osver: str, langs: list[str]) -> bool: + """Check OR (||) test result""" + conds = str.split("||") + for c in conds: + if "OSProcessorFamily" in c: + if do_test(c, osProc) is True: + return True + + if "OSVersion" in c: + if do_test(c, osver) is True: + return True + + if "installLanguage" in c: + if "all" in langs: + return True + + if do_test(c, langs) is True: + return True + + return False + + +def condition_filter(pkgJson: dict, langs: list[str]) -> dict: + """Filter packages by condition statements""" + osver = cfg["osVersion"] + osProc = "64-bit" + if cfg["reqAppPlatform"] == "win32": + osProc = "32-bit" + + packages = pkgJson["Packages"]["Package"] + + newPkgs = [] + for pkg in packages: + # append_file("conditions.txt", pkg.get("Condition")) + # continue + + if "Condition" in pkg: + conds = pkg.get("Condition") + if "||" in conds: + if test_or(conds, osProc, osver, langs) == True: + newPkgs.append(pkg) + else: + if test_and(conds, osProc, osver, langs) == True: + newPkgs.append(pkg) + + # premiere pro + elif "-esl_lp_" in pkg["PackageName"]: + app, pproLang = pkg["PackageName"].split("-") + pproLang = pproLang.replace("esl_lp_", "") + for l in langs: + if l == "all": + continue + main, locale = l.split("_") + if main == pproLang: + newPkgs.append(pkg) + # for china languages + if main == "zh": + if pproLang == "cmn" or pproLang == "yue": + newPkgs.append(pkg) + + else: + newPkgs.append(pkg) + + pkgJson["Packages"]["Package"] = newPkgs + + return pkgJson + + +def module_filter(pkgJson: dict) -> dict: + """Rebuild module for selected packages""" + if "Modules" in pkgJson: + packageNames = [] + for names in pkgJson["Packages"]["Package"]: + packageNames.append(names["PackageName"]) + + allModules = pkgJson["Modules"]["Module"] + newModules = [] + for module in allModules: + refPackage = module["ReferencePackages"]["ReferencePackage"] + for names in refPackage: + if names in packageNames: + newModules.append(module) + + pkgJson["Modules"]["Module"] = newModules + return pkgJson + + +def get_package_url(pkgJson: dict) -> list[str]: + """Get package count and download url""" + count = core = 0 + pkgUrl = [] + for pkg in pkgJson["Packages"]["Package"]: + count += 1 + pkgUrl.append(pkg["Path"]) + if pkg.get("Type") == "core": + core += 1 + + print(f"\n{core} core and {count - core} none-core packages to download.") + + return pkgUrl + + +def package_filter(pkgJson: dict, lang: list[str]): + """Filter and rebuild packages by conditions and languages""" + + # filter unused languages data + pkgJson = language_filter(pkgJson, lang) + + # filter by conditions string + pkgJson = condition_filter(pkgJson, lang) + + # filter unused module + pkgJson = module_filter(pkgJson) + + # get package urls + pkgUrl = get_package_url(pkgJson) + + return pkgJson, pkgUrl + + +def package_download(url: str, destDir: str, code: str, ver: str, name=None) -> None: """Download a product package""" if not name: name = os.path.basename(url) - print("[{}_{}] Downloading {}".format(s, v, name)) - return download_progress(url, dest_dir) + print("\n[{}_{}] Downloading {}".format(code, ver, name)) + download_file(url, destDir) -def download_acrobat(appInfo, cdn, downList): - # download manifest file - response = session.get( - cdn + appInfo["manifestURL"], stream=True, headers=ADOBE_REQ_HEADERS - ) - response.encoding = "utf-8" - manifest = ET.fromstring(response.text) +def get_appjson(prodInfo: list) -> dict: + """Download package json file""" + if "appType" in prodInfo and prodInfo["appType"] == "dep": + dep_data = list(prodInfo["versions"].values()) + firstItem = dep_data[0] + appGuid = firstItem["buildGuid"] + else: + appGuid = prodInfo["buildGuid"] + + """Retrieve JSON.""" + headers = ADOBE_REQ_HEADERS.copy() + headers["x-adobe-build-guid"] = appGuid + + print("\nDownloading Application.json file ...") + #fileName = prodInfo["sapCode"] + "_Application.json" + return download_json(ADOBE_APPLICATION_JSON_URL, headers) + + +def write_driver_xml(pkgJson: dict, pkgDir: str) -> None: + """Generate Diver.xml and save to product dir""" + driverInfo = ET.Element("DriverInfo") + productInfo = ET.SubElement(driverInfo, "ProductInfo") + for key, val in dict( + { + "Name": "Adobe {}".format(pkgJson["Name"]), + "SAPCode": pkgJson["SAPCode"], + "CodexVersion": pkgJson["CodexVersion"], + "BaseVersion": pkgJson["BaseVersion"], + "Platform": pkgJson["Platform"], + "EsdDirectory": (os.path.join("./", pkgJson["SAPCode"])), + } + ).items(): + child = ET.Element(key) + child.text = str(val) + productInfo.append(child) + + if "Dependencies" in pkgJson: + depRoot = ET.SubElement(productInfo, "Dependencies") + for d in pkgJson["Dependencies"]["Dependency"]: + deps = ET.Element("Dependency") + for key, val in dict( + { + "SAPCode": d["SAPCode"], + "BaseVersion": d["BaseVersion"], + "EsdDirectory": (os.path.join("./", d["SAPCode"])), + } + ).items(): + child = ET.Element(key) + child.text = str(val) + deps.append(child) + depRoot.append(deps) + + # for url > v5 + if "IsNonCCProduct" in pkgJson and "IsNglEnabled" in pkgJson: + for key, val in dict( + { + "IsNonCCProduct": pkgJson["IsNonCCProduct"], + "IsNglEnabled": True if "NglLicensingInfo" in pkgJson else False, + } + ).items(): + child = ET.Element(key) + child.text = str(val) + productInfo.append(child) + + langRoot = ET.SubElement(productInfo, "SupportedLanguages") + for lg in pkgJson["SupportedLanguages"]["Language"]: + for key, val in dict({"Language": ""}).items(): + child = ET.Element(key) + child.set("locale", lg["locale"]) + langRoot.append(child) + + # suppress error on dep package download + if "MinimumSupportedClientVersion" in pkgJson and "HDBuilderVersion" in pkgJson: + for key, val in dict( + { + "MinimumSupportedClientVersion": pkgJson["MinimumSupportedClientVersion"], + "HDBuilderVersion": pkgJson["HDBuilderVersion"], + } + ).items(): + child = ET.Element(key) + child.text = str(val) + productInfo.append(child) + + if pkgJson["SAPCode"] == "LTRM": + requestInfo = ET.SubElement(driverInfo, "RequestInfo") + reqSub = ET.SubElement(requestInfo, "IsEnterpriseDeployment") + reqSub.text = "true" + + tree = ET.ElementTree(driverInfo) + ET.indent(tree, space=" ", level=0) + + fileName = pkgJson["SAPCode"] + "-" + "Driver.xml" + xml_file = os.path.join(pkgDir, fileName) + tree.write(xml_file, encoding="utf-8", xml_declaration=True) + + +def product_download(prodInfo: list, allProducts: dict, reqLang: list) -> None: + """Download product related packages""" + sapCode = prodInfo["sapCode"] + + # create product packages dir + pkgDir = os.path.join(cfg['productDir'], sapCode) + os.makedirs(pkgDir, exist_ok=True) + + appJsonData = get_appjson(prodInfo) + + # filter out unused packages and resource urls + appJsonData, urls = package_filter(appJsonData, reqLang) + + # download packages + cdn = appJsonData["Cdn"]["Secure"] + version = appJsonData["ProductVersion"] + + if allProducts[sapCode]["appType"] == "app": + if appJsonData.get("AddRemoveInfo"): + appName = appJsonData["AddRemoveInfo"]["DisplayName"]["Language"][0]["value"] + else: + appName = "Adobe " + appJsonData.get("FamilyName") + + print(f"\nDownloading packages for {appName}, version-{version}") + + print("\nCreating Driver.xml file...") + write_driver_xml(appJsonData, cfg['productDir']) + + print("\nCreating Application.json file...") + create_json(os.path.join(pkgDir, "Application.json"), appJsonData) + + for url in urls: + url = cdn + url + + package_download(url, pkgDir, sapCode, version) + + if "Dependencies" in appJsonData: + print("\nDownloading dependency packages...") + for dependency in appJsonData["Dependencies"]["Dependency"]: + depSap = dependency["SAPCode"] + depPackage = allProducts.get(depSap) + + product_download(depPackage, allProducts, reqLang) + + +def download_acrobat(prodInfo, toDown): + """Download acrobat installer or updates""" + url = cfg['cdn'] + prodInfo["manifestURL"] + + print("\nDownloading manifest.xml ...") + manifest = download_xml(url, ADOBE_REQ_HEADERS) # check available products assetList = manifest.findall("./asset_list/asset") productList = {} prodNum = 0 + availNums = [] full = None for asset in assetList: prodNum += 1 + availNums.append(str(prodNum)) assetPath = asset.find("./asset_path").text baseVersion = asset.find(".//baseVersion") if baseVersion is not None: @@ -614,18 +1118,20 @@ def download_acrobat(appInfo, cdn, downList): productList[str(prodNum)] = { "assetName": os.path.basename(assetPath), "assetSize": asset.find("./asset_size").text, - "downloadUrl": assetPath, + "assetPath": assetPath, "baseVersion": baseVersion, } + # select product to download selectedCode = None - if len(downList) > 1: + if len(toDown) > 1: selectedCode = full while selectedCode is None: print("\nAvailable downloads\n") for n, p in productList.items(): if p["baseVersion"] is None: + full = n print( "{}. {}{} Full Installer".format( n, p["assetName"], (35 - len(p["assetName"])) * " " @@ -642,438 +1148,79 @@ def download_acrobat(appInfo, cdn, downList): ) val = input( - "\nPlease enter the number from list above or blank to download full installer: " + "\nPlease enter the number from the list above or full installer: " ) or full - if val in productList: + if val in availNums: selectedCode = val elif val == "": print("No product selected! Please use a value from the list above.") else: print(f"{val} is not available! Please check your input.") - downloadURL = productList[selectedCode]["downloadUrl"] + aproDir = os.path.join(cfg["productDir"], "APRO") + os.makedirs(aproDir, exist_ok=True) - dest = get_download_path() - sapCode = appInfo["sapCode"] - version = appInfo["productVersion"] - name = os.path.basename(downloadURL) - filePath = os.path.join(dest, name) + assetPath = productList[selectedCode]["assetPath"] - if file_download(downloadURL, dest, sapCode, version, name) is True: - print(f"\n{name} was successfully downloaded to: {filePath}") - return + print("\nDownloading Adobe Acrobat v. {} for {}...".format( + prodInfo["productVersion"], prodInfo["appPlatform"])) + + download_file(assetPath, aproDir) -def get_application_json(buildGuid): - """Retrieve JSON.""" - headers = ADOBE_REQ_HEADERS.copy() - headers["x-adobe-build-guid"] = buildGuid - response = session.get(ADOBE_APPLICATION_JSON_URL, headers=headers) - response.encoding = "utf-8" - return json.loads(response.content) - - -def save_application_json(pkg_dir, json_data): - app_json_path = os.path.join(pkg_dir, "Application.json") - with open(app_json_path, "w+") as file: - json.dump(json_data, file, separators=(",", ":")) - - -def write_driver_xml(json, pds_dir, prefix=""): - driverInfo = ET.Element("DriverInfo") - productInfo = ET.SubElement(driverInfo, "ProductInfo") - for key, val in dict( - { - "Name": "Adobe {}".format(json["Name"]), - "SAPCode": json["SAPCode"], - "CodexVersion": json["CodexVersion"], - "BaseVersion": json["BaseVersion"], - "Platform": json["Platform"], - "EsdDirectory": (os.path.join("./", json["SAPCode"])), - } - ).items(): - child = ET.Element(key) - child.text = str(val) - productInfo.append(child) - - if "Dependencies" in json: - dep_root = ET.SubElement(productInfo, "Dependencies") - for d in json["Dependencies"]["Dependency"]: - deps = ET.Element("Dependency") - for key, val in dict( - { - "SAPCode": d["SAPCode"], - "BaseVersion": d["BaseVersion"], - "EsdDirectory": (os.path.join("./", d["SAPCode"])), - } - ).items(): - child = ET.Element(key) - child.text = str(val) - deps.append(child) - dep_root.append(deps) - - # for url > v5 - if "IsNonCCProduct" in json and "IsNglEnabled" in json: - for key, val in dict( - { - "IsNonCCProduct": json["IsNonCCProduct"], - "IsNglEnabled": True if "NglLicensingInfo" in json else False, - } - ).items(): - child = ET.Element(key) - child.text = str(val) - productInfo.append(child) - - lang_root = ET.SubElement(productInfo, "SupportedLanguages") - for lg in json["SupportedLanguages"]["Language"]: - for key, val in dict({"Language": ""}).items(): - child = ET.Element(key) - child.set("locale", lg["locale"]) - lang_root.append(child) - - # suppress error on dep package download - if "MinimumSupportedClientVersion" in json and "HDBuilderVersion" in json: - for key, val in dict( - { - "MinimumSupportedClientVersion": json["MinimumSupportedClientVersion"], - "HDBuilderVersion": json["HDBuilderVersion"], - } - ).items(): - child = ET.Element(key) - child.text = str(val) - productInfo.append(child) - - if json["SAPCode"] == "LTRM": - requestInfo = ET.SubElement(driverInfo, "RequestInfo") - req_sub = ET.SubElement(requestInfo, "IsEnterpriseDeployment") - req_sub.text = "true" - - tree = ET.ElementTree(driverInfo) - ET.indent(tree, space=" ", level=0) - xml_file = os.path.join(pds_dir, prefix + "Driver.xml") - tree.write(xml_file, encoding="utf-8", xml_declaration=True) - - -def condition_test(package, language, ProcessorFamily, condition): - packageType = ProcessorFamily - if "ProcessorFamily" in package: - packageType = package["ProcessorFamily"] - - if "==" in condition: - testSubject, testValue = condition.split("==") - testOption = operator.eq - elif "!=" in condition: - testSubject, testValue = condition.split("!=") - testOption = operator.ne - elif "<=" in condition: - testSubject, testValue = condition.split("<=") - testOption = operator.le - elif ">=" in condition: - testSubject, testValue = condition.split(">=") - testOption = operator.ge - elif ">" in condition: - testSubject, testValue = condition.split(">") - testOption = operator.gt - elif "<" in condition: - testSubject, testValue = condition.split("<") - testOption = operator.lt - - # start testing - if testSubject.strip() == "[OSProcessorFamily]": - return testOption(testValue.strip(), ProcessorFamily) - elif testSubject.strip() == "[OSVersion]": - getWinVer = sys.getwindowsversion() - winVer = "{}.{}".format(getWinVer.major, getWinVer.minor) - return testOption(testValue.strip(), winVer) - elif testSubject.strip() == "[installLanguage]" and packageType == ProcessorFamily: - if language.lower() == "all" or language.lower() == "mul": - return True - else: - return testOption(testValue.strip(), language) - else: - # alway true on unset - return True - - -def condition_filter(package, language, ProcessorFamily): - conditions = [] - conditionString = package["Condition"].strip() - if "&&" in conditionString: - conditions = conditionString.split("&&") - for condition in conditions: - testResult = condition_test( - package, language, ProcessorFamily, condition) - if testResult is False: - break - - elif "||" in conditionString: - conditions = conditionString.split("||") - for condition in conditions: - testResult = condition_test( - package, language, ProcessorFamily, condition) - if testResult is True: - break - else: - testResult = condition_test( - package, language, ProcessorFamily, conditionString) - - return testResult - - -def language_for_premiere(language): - if "_" in language: - main, locale = language.split("_") - return "-esl_lp_" + main - return language - - -def package_filter(package, language, platform): - coreCount = 0 - noneCoreCount = 0 - urlPath = [] - newPackage = [] - - ProcessorFamily = "64-bit" - if platform == "win32": - ProcessorFamily = "32-bit" - - for pkg in package: - if pkg.get("Type") and pkg["Type"] == "core": - if "Condition" in pkg: - if condition_filter(pkg, language, ProcessorFamily) == True: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - coreCount += 1 - elif "ProcessorFamily" in pkg: - if platform == "win32": - if pkg["ProcessorFamily"] == ProcessorFamily: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - coreCount += 1 - else: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - coreCount += 1 - else: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - coreCount += 1 - else: - if "Condition" in pkg: - if condition_filter(pkg, language, ProcessorFamily) == True: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - noneCoreCount += 1 - elif "ProcessorFamily" in pkg: - if platform == "win32": - if pkg["ProcessorFamily"] == ProcessorFamily: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - noneCoreCount += 1 - else: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - noneCoreCount += 1 - else: - # for premiere pro - if "-esl_lp_" in pkg["PackageName"]: - if language_for_premiere(language) in pkg["PackageName"]: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - noneCoreCount += 1 - else: - newPackage.append(pkg) - urlPath.append(pkg["Path"]) - noneCoreCount += 1 - - print( - f"\nSelected {coreCount} core packages and {noneCoreCount} non-core packages" - ) - - return urlPath, newPackage - - -# https://stackoverflow.com/questions/71543579/python-find-and-replace-all-values-under-a-certain-key-in-a-nested-dictionary -def language_filter(data, language): - key = "Language" - if isinstance(data, dict): - # filter by locale - filtered = {} - for k, v in data.items(): - if k == key: - for lc in v: - if lc["locale"] == language or lc["locale"] == "mul": - filtered = [lc] - # replace with filtered result - return { - k: filtered if k == key and v else language_filter(v, language) - for k, v in data.items() - } - elif isinstance(data, list): - return [language_filter(v, language) for v in data] - else: - return data - - -def dependencies_download(json, products, pds_dir, installLanguage, selectedPlatform): - for dependency in json["Dependencies"]["Dependency"]: - depSap = dependency["SAPCode"] - dep_dir = os.path.join(pds_dir, depSap) - os.makedirs(dep_dir, exist_ok=True) - - depPackage = products.get(depSap) - dep_data = list(depPackage["versions"].values()) - firstItem = dep_data[0] - dep_json = get_application_json(firstItem["buildGuid"]) - if ( - package_download(dep_json, dep_dir, - installLanguage, selectedPlatform) - is False - ): - print("\nCannot download dependency package") - break - return - - -def package_download(json, pkg_dir, language, selectedPlatform): - allPackages = json["Packages"]["Package"] - cdn = json["Cdn"]["Secure"] - sapCode = json["SAPCode"] - version = json["ProductVersion"] - urls, package = package_filter(allPackages, language, selectedPlatform) - - # module filter - if "Modules" in json: - packageNames = [] - for names in package: - packageNames.append(names["PackageName"]) - - allModules = json["Modules"]["Module"] - newModules = [] - for module in allModules: - refPackage = module["ReferencePackages"]["ReferencePackage"] - for names in refPackage: - if names in packageNames: - newModules.append(module) - - json["Modules"]["Module"] = newModules - - # filtered json data - json["Packages"]["Package"] = package - - print("\nCreating Application.json\n") - - save_application_json(pkg_dir, json) - - # download packages - for url in urls: - if file_download(cdn + url, pkg_dir, sapCode, version) is False: - return False - return True - - -def run_ccdl(products, cdn, sapCodes, selectedPlatform): +def run_ccdl(allProducts: dict) -> None: """Run Main execution.""" - # get product list - productLists = product_code(products, sapCodes) + toDown = download_list(allProducts) - for sapCode in productLists: - product = products.get(sapCode) + for sapCode in toDown: + product = allProducts.get(sapCode) - # version select - versions = product["versions"] - if len(productLists) > 1: - selectedVersion = get_last_version(versions) - else: - selectedVersion = product_version(product, versions) + batch = False + if len(toDown) > 1: + # select app by version + batch = True - # product to download - prodInfo = versions[selectedVersion] + prodInfo = select_app_version(product, batch) # language select - supportedLangs = prodInfo["supportedLanguages"] - installLanguage = install_language(supportedLangs) + appLangs = prodInfo["supportedLanguages"] + installLanguage = install_language(appLangs) + + if "productIcons" in prodInfo: + download_icons(prodInfo) # download by manifest url if sapCode == "APRO": - download_acrobat(prodInfo, cdn, productLists) + download_acrobat(prodInfo, toDown) continue - # main product - print( - "\nPrepare to download Adobe {}-{}-{}-{}".format( - prodInfo["displayName"], - prodInfo["productVersion"], - installLanguage, - prodInfo["appPlatform"], - ) - ) - - dest = get_download_path() - - # download icons - if args.productIcons: - icons_download(prodInfo, dest) - - # create products directory - products_dir = os.path.join(dest, "products") - os.makedirs(products_dir, exist_ok=True) - - # create product packages dir - package_dir = os.path.join(products_dir, sapCode) - os.makedirs(package_dir, exist_ok=True) - - app_json = get_application_json(prodInfo["buildGuid"]) - - # filter out unused languages from Application.json file - if installLanguage.lower() != "all": - app_json = language_filter(app_json, installLanguage) - - print("\nDownloading main app package") - if ( - package_download(app_json, package_dir, - installLanguage, selectedPlatform) - is False - ): - print("\nCannot download all packages") - - if "Dependencies" in app_json: - print("\nDownloading dependency packages") - dependencies_download( - app_json, products, products_dir, installLanguage, selectedPlatform - ) - - print("Generating Driver.xml") - prefix = app_json["SAPCode"] + "-" - write_driver_xml(app_json, products_dir, prefix) - - print( - "\nSuccessfully downloaded Adobe {} v-{}".format( - prodInfo["displayName"], - prodInfo["productVersion"], - ) - ) - - return + product_download(prodInfo, allProducts, installLanguage) if __name__ == "__main__": - show_version(SCRIPT_NAME, VERSION_STR) - - args = get_arguments() + show_info(SCRIPT_NAME, VERSION_STR, 6, "=") - products, cdn, sapCodes, selectedPlatform = get_products() + # get and set configuration + cfg = set_config() + + # get available products + allProducts = get_products(cfg) while True: try: - run_ccdl(products, cdn, sapCodes, selectedPlatform) - # cleanup old sapcodes - args.sapCode = None - if args.noRepeatPrompt or not questiony( - "\n\nDo you want to download another package" + # run main program + run_ccdl(allProducts) + + # reset download list + cfg["toDown"] = None + + if cfg["noRepeat"] or not questiony( + "\nDo you want to download another package" ): + print("Bye!") break + except KeyboardInterrupt: - print("\nProgram was terminated by user") + print("\nTerminated by user") sys.exit() diff --git a/suite_installer/Readme.md b/suite_installer/Readme.md index 6d69329..a9c7523 100644 --- a/suite_installer/Readme.md +++ b/suite_installer/Readme.md @@ -6,7 +6,7 @@ .\Set-up.exe ``` -# How to +## How to 1. Download desired products. 2. Move all packages folders to products (No need to move __prefix__Driver.xml files) 3. Copy Set-up.exe and packages files to current folder @@ -18,5 +18,5 @@ ```` 6. SuiteInfo.xml can be found in products directory. (You can manually edit too) -# Note -Acrobat Pro DC is not HD installer type. You can manually edit SuiteInfo.xml (use APRO.xml file) and add acrobat installer files to products folder. \ No newline at end of file +### Note +1. Acrobat Pro DC is not HD installer type. You can manually edit SuiteInfo.xml (use APRO.xml file) and add acrobat installer files to products folder. \ No newline at end of file