tis-av1-video-extension icon

AV1 Video Extension

Paquet d’installation silencieuse pour AV1 Video Extension

1.3.15.0-63

  • package: tis-av1-video-extension
  • name: AV1 Video Extension
  • version: 1.3.15.0-63
  • categories: Media,Extension
  • maintainer: WAPT Team,Tranquil IT,Jimmy PELÉ,Pierre COSSON
  • licence: proprietary_free,wapt_public
  • locale: all
  • target_os: windows
  • architecture: all
  • signature_date:
  • size: 5.47 Mo
  • installed_size: 3.98 Mo

package           : tis-av1-video-extension
version           : 1.3.15.0-63
architecture      : all
section           : base
priority          : optional
name              : AV1 Video Extension
categories        : Media,Extension
maintainer        : WAPT Team,Tranquil IT,Jimmy PELÉ,Pierre COSSON
description       : Play AV1 videos in your favorite video app on your Windows device. This extension helps video apps installed on Windows play videos that have been encoded using the AV1 video coding standard developed by the Alliance for Open Media
depends           : 
conflicts         : 
maturity          : PROD
locale            : all
target_os         : windows
min_wapt_version  : 2.3
sources           : https://apps.microsoft.com/store/detail/9MVZQVXJBQ9V
installed_size    : 3979089
impacted_process  : 
description_fr    : Lisez les vidéos AV1 dans votre application vidéo préférée sur votre appareil Windows. Cette extension permet aux applications vidéo installées sur Windows de lire les vidéos encodées à l'aide de la norme de codage vidéo AV1 développée par l'Alliance for Open Media
description_pl    : Odtwarzanie filmów AV1 w ulubionej aplikacji wideo na urządzeniu z systemem Windows. To rozszerzenie pomaga aplikacjom wideo zainstalowanym w systemie Windows odtwarzać filmy, które zostały zakodowane przy użyciu standardu kodowania wideo AV1 opracowanego przez Alliance for Open Media
description_de    : Spielen Sie AV1-Videos in Ihrer Lieblingsvideoanwendung auf Ihrem Windows-Gerät ab. Mit dieser Erweiterung können auf Windows installierte Videoanwendungen Videos wiedergeben, die mit dem von der Alliance for Open Media entwickelten AV1-Videocodierungsstandard kodiert wurden
description_es    : Reproduzca vídeos AV1 en su aplicación de vídeo favorita en su dispositivo Windows. Esta extensión ayuda a las aplicaciones de vídeo instaladas en Windows a reproducir vídeos codificados con el estándar de codificación de vídeo AV1 desarrollado por la Alliance for Open Media
description_pt    : Reproduza vídeos AV1 na sua aplicação de vídeo favorita no seu dispositivo Windows. Esta extensão ajuda as aplicações de vídeo instaladas no Windows a reproduzir vídeos que foram codificados utilizando a norma de codificação de vídeo AV1 desenvolvida pela Alliance for Open Media
description_it    : Riproducete i video AV1 nella vostra applicazione video preferita sul vostro dispositivo Windows. Questa estensione aiuta le app video installate su Windows a riprodurre i video codificati con lo standard di codifica video AV1 sviluppato da Alliance for Open Media
description_nl    : Speel AV1-video's af in je favoriete video-app op je Windows-apparaat. Deze extensie helpt video-apps die op Windows zijn geïnstalleerd video's af te spelen die zijn gecodeerd met de AV1-videocoderingsstandaard, ontwikkeld door de Alliance for Open Media
description_ru    : Воспроизведение видеороликов AV1 в любимом видеоприложении на устройстве Windows. Это расширение помогает видеоприложениям, установленным на Windows, воспроизводить видео, закодированное с использованием стандарта кодирования видео AV1, разработанного Альянсом за открытые медиа
audit_schedule    : 
editor            : 
keywords          : 
licence           : proprietary_free,wapt_public
homepage          : 
package_uuid      : 411bd394-45bc-4524-8ff5-0e53611e375f
valid_from        : 
valid_until       : 
forced_install_on : 
changelog         : 
min_os_version    : 10.0.17763
max_os_version    : 
icon_sha256sum    : 5cd06abee4d9bc5102f5bf44b601bf5ee747193df5321c6e1fa2f0bd4ad83699
signer            : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date    : 2025-05-07T12:03:25.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature         : T6OysipRPsZkSzBQTkC2az4mqUEIvXcLp7bJkxVYOONk1IsVDuUTcaynnILttzrUa7rk7+5SBTOQuNgoQ14KD1kMgwwZ67jUJdlF84/pAc0Z6O1/UdDVqoNmLNQZeb09lwoAco77C/x3o7AjUM4kZGvn7iNXqAYrIMDTRJ98ZeZuhh5558p+byRcKXF5eMSeKqPNieiCPqFowGhE86rAEU3NtFNPrfxToRYO3GsmDU9sOYNcukrwHuAU8bPDPP6a+SmGFQsHNUbxl0omME5GH387igJcBRTN646FkypCwrQ8zkGJ2Js4pY/BNUCoVGSNJrLv5v1Ume/BVknabEqzMg==

# -*- coding: utf-8 -*-
from setuphelpers import *


appx_package_name = "Microsoft.AV1VideoExtension"
appx_dir = makepath(programfiles, "WindowsAppsInstallers")


def install():
    # Declare local variables
    bins_dir = control.package.split("-", 1)[1]
    old_appx_bins_dir = makepath(appx_dir, bins_dir)
    appx_bins_dir = makepath(os.getcwd(), bins_dir)

    # Removing sources because they are no longer needed
    if isdir(old_appx_bins_dir):
        print("Removing: %s" % (old_appx_bins_dir))
        remove_tree(old_appx_bins_dir)
    if dir_is_empty(appx_dir):
        print("Removing: %s since it is empty" % (appx_dir))
        remove_tree(appx_dir)

    # Removing binaries of different architectures
    for f in glob.glob(appx_bins_dir + "/*"):
        fname = f.split(os.sep)[-1]
        if control.architecture == "all":
            if "x86" in glob.glob(makepath(appx_bins_dir, f"{appx_package_name}_*"))[0].split(os.sep)[-1]:
                if not "x86" in fname and not "neutral" in fname:
                    remove_file(f)
            else:
                if not get_host_architecture() in fname and not "neutral" in fname:
                    remove_file(f)
        else:
            if not get_host_architecture() in fname and not "neutral" in fname:
                remove_file(f)
    bin_path = glob.glob(makepath(appx_bins_dir, f"{appx_package_name}_*"))[0]
    dependencies_pathes = ",".join([f'"{a}"' for a in glob.glob(makepath(appx_bins_dir, "*")) if not appx_package_name in a])
    add_appx_cmd = f'Add-AppxProvisionedPackage -Online -PackagePath "{bin_path}" -SkipLicense'
    if dependencies_pathes:
        add_appx_cmd += f" -DependencyPackagePath {dependencies_pathes}"

    # Installing the UWP application if needed
    appxprovisionedpackage = run_powershell(f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like "{appx_package_name}"')
    if appxprovisionedpackage is None:
        appxprovisionedpackage = {"Version": "0"}

    if Version(appxprovisionedpackage["Version"], 4) < Version(control.get_software_version(), 4) or force:
        print(f"Installing: {bin_path.split(os.sep)[-1]} ({control.get_software_version()})")
        killalltasks(ensure_list(control.impacted_process))
        run_powershell(add_appx_cmd, output_format="text")
    else:
        print(f'{appxprovisionedpackage["PackageName"]} is already installed and up-to-date.')


def uninstall():
    # Declare local variables
    bins_dir = control.package.split("-", 1)[1]
    appx_bins_dir = makepath(appx_dir, bins_dir)

    print(f"Removing AppX: {appx_package_name}")
    remove_appx(appx_package_name)


def audit():
    # Declaring local variables
    audit_result = "OK"
    audit_version = True
    appxprovisionedpackage = run_powershell(f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like "{appx_package_name}"')

    # Auditing software
    if appxprovisionedpackage is None:
        print(f"{appx_package_name} is not installed.")
        audit_result = "ERROR"
    elif audit_version:
        if Version(appxprovisionedpackage.get("Version", "0"), 4) < Version(control.get_software_version(), 4):
            print(
                f'{appxprovisionedpackage["PackageName"]} is installed in version: {appxprovisionedpackage["Version"]} instead of: {control.get_software_version()}.'
            )
            audit_result = "WARNING"
        else:
            print(f'{appxprovisionedpackage["PackageName"]} is installed and up-to-date.')
    else:
        print(f'{appxprovisionedpackage["PackageName"]} is installed.')

    return audit_result


def remove_appx(package, default_user=True):
    """Remove Windows AppX package from the computer environment, excluding NonRemovable packages.

    Args:
        package (str): AppX package name. You can use an asterisk (*) as a wildcard.
        default_user (bool): Remove AppX package from the Windows image to prevent installation for new users.

    .. versionadded:: 2.2

    .. versionchanged:: 2.5
        No longer try to remove NonRemovable AppX package

    """
    if running_as_admin() or running_as_system():
        if default_user:
            run_powershell(
                f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like "{package}" | Remove-AppxProvisionedPackage -Online -AllUsers',
                output_format="text",
            )
        run_powershell(
            r'Get-AppxPackage -Name "%s" -AllUsers | Where-Object {{ -not ($_.NonRemovable) }} | Remove-AppxPackage -AllUsers' % package,
            output_format="text",
        )
    else:
        run_powershell(r'Get-AppxPackage -Name "%s" | Where-Object {{ -not ($_.NonRemovable) }} | Remove-AppxPackage' % package, output_format="text")

# -*- coding: utf-8 -*-
from setuphelpers import *
import requests
import re
import json
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
from setupdevhelpers import *


def update_package():
    # Declaring local variables
    package_updated = False
    proxies = get_proxies_from_wapt_console()
    if not proxies:
        proxies = get_proxies()
    microsoft_store_url = control.sources
    if not microsoft_store_url:
        store_id = ask_input(
            control.package,
            "Enter the application ProductId or the link from the Microsoft Store (web address: https://apps.microsoft.com/store/apps)",
            microsoft_store_url,
            raise_error=True,
        ).split("/")[-1]
    else:
        store_id = microsoft_store_url.split("/")[-1]
    store_id = store_id.split("?")[0].split("#")[0].upper()
    if store_id:
        microsoft_store_url = "https://apps.microsoft.com/store/detail/%s" % store_id
        control.sources = microsoft_store_url
        control.save_control_to_wapt()
    package_prefix = control.package.split("-")[0]
    selected = None

    # check setup.py incase the package name does not match the installer file
    appx_package_name = ""
    with open("setup.py", "r", encoding="utf8") as f:
        for line in f.readlines():
            if line.startswith("appx_package_name"):
                appx_package_name = line.split("=")[1].split('"')[1]
                break
    old_appx_package_name = appx_package_name

    # Getting info from adguard api
    res = requests.post(
        "https://store.rg-adguard.net/api/GetFiles",
        "type=ProductId&url=%s&ring=RP&lang=fr-FR" % store_id,
        headers={"content-type": "application/x-www-form-urlencoded"},
        proxies=proxies,
    )
    all_files = []
    for bs_search in bs_find_all(res.text, "a"):
        if not "BlockMap" in bs_search.text and not "eappxbundle" in bs_search.text and not "emsixbundle" in bs_search.text:
            # bin_name = bs_search.text.replace("~", "_")
            bin_name = str(bs_search.text)
            if not get_file_extension(bin_name):
                continue
            version = bin_name.split("_")[1]
            download_url = bs_search["href"]
            pkg_splitted = re.split(r"_\d+\.", bin_name)[0]
            package_name = package_prefix + "-" + pkg_splitted.split("_")[0].replace(".", "-").lower()
            software_name = bin_name.split("_")[0].replace("-", " ").replace(".", " ")
            package_arch = get_uwp_filename_arch(bin_name, appx_package_name)
            file_dict = {
                "version": version,
                "bin_name": bin_name,
                "package_name": package_name,
                "software_name": software_name,
                "package_arch": package_arch,
                "download_url": download_url,
            }
            all_files.append(file_dict)
    if (
        "template-microsoft-store" in control.package
        or not appx_package_name
        or not len([a for a in all_files if appx_package_name in a["bin_name"]]) != 0
    ):
        if not all_files:
            error(f"API returned an empty list for URL: {microsoft_store_url}, please try again")
        selected = ask_grid(
            "Please select the App version that you want to package",
            all_files,
            "GRT_SELECTED",
            '{"columns":[{"propertyname":"version","datatype":"String","required":false,"readonly":false,"width":130},{"propertyname":"bin_name","datatype":"String","required":false,"readonly":false,"width":420},{"propertyname":"package_name","datatype":"String","required":false,"readonly":false,"width":190},{"propertyname":"software_name","datatype":"String","required":false,"readonly":false,"width":172},{"propertyname":"package_arch","datatype":"String","required":false,"readonly":false,"width":88},{"propertyname":"download_url","datatype":"String","required":false,"readonly":false,"width":1472}]}',
        )
        appx_package_name = selected[0]["bin_name"].split("_")[0]

    # Avoiding downloads loop and avoid keeping sources of other apps
    bins_dir = control.package.split("-", 1)[1]
    for dir_name in glob.glob("**/"):
        dir_name = dir_name.split(os.sep)[0]
        if dir_name in ["WAPT", "__pycache__"]:
            continue
        if dir_name == bins_dir:
            for f in (
                glob.glob(f"{dir_name}/*.appxbundle")
                + glob.glob(f"{dir_name}/*.msixbundle")
                + glob.glob(f"{dir_name}/*.appx")
                + glob.glob(f"{dir_name}/*.msix")
            ):
                shutil.move(f, ".")
        else:
            remove_tree(dir_name)
            if isfile("package.json"):
                remove_file("package.json")

    # Updating package.json ignored_versions list
    if isfile("package.json"):
        package_json = json_load_file("package.json")
    else:
        package_json = {"version_prefix": None, "ignored_versions": []}
    if selected:
        ignored_versions = list(
            set(
                package_json["ignored_versions"]
                + [v["version"] for v in all_files if appx_package_name in v["bin_name"] and v["version"] != selected[0]["version"]]
            )
        )
        ignored_versions.sort()
        package_json["ignored_versions"] = ignored_versions
        json_write_file("package.json", package_json)
    else:
        ignored_versions = package_json["ignored_versions"]
    version_prefix = package_json.get("version_prefix", None)

    # Downloading app files
    download_app_files(all_files, appx_package_name, proxies=proxies, ignored_versions=ignored_versions, version_prefix=version_prefix)

    # # Import xmltodict for make_uwp_app_dict()
    # if not isfile("xmltodict.py"):
    #     pip_download_xmltodict = "waptpython -m pip download xmltodict -d %s" % basedir
    #     if proxies:
    #         pip_download_xmltodict += " --proxy %s" % proxies["http"]
    #     run(pip_download_xmltodict)
    #     unzip(glob.glob("*.whl")[0], ".", "xmltodict.py")
    #     remove_file(glob.glob("*.whl")[0])

    # Keep app files
    uwp_app_dict = make_uwp_app_dict(appx_package_name)
    newer_uwp_app = get_newer_uwp_app(uwp_app_dict, tdf_list=None)
    version = newer_uwp_app["Version"]

    # Downloading dependency files
    dependencies_to_download = []
    if newer_uwp_app["Dependencies"]:
        for dependency in newer_uwp_app["Dependencies"]:
            dependencies_to_download.append(get_newer_uwp_depency(dependency, all_files, min_version=dependency["MinVersion"]))
    if dependencies_to_download:
        for dependency_file in all_files:
            latest_bin = dependency_file["bin_name"]
            if not True in [d in latest_bin for d in dependencies_to_download]:  # ignore unecessary dependencies
                continue
            if not "all" in ensure_list(control.architecture):
                if not get_uwp_filename_arch(latest_bin) in ensure_list(control.architecture) and not "neutral" in latest_bin:
                    if isfile(latest_bin):
                        remove_file(latest_bin)
                    continue
            if latest_bin.split(".")[-1].lower().startswith("e"):  # ignore encrypted uwp apps
                continue
            download_url = dependency_file["download_url"]
            if download_url.split("/")[2].endswith("microsoft.com"):
                if not isfile(latest_bin):
                    print("Downloading: %s" % latest_bin)
                    wget(download_url, latest_bin, proxies=proxies)
                else:
                    print("Binary is present: %s" % latest_bin)
            else:
                error("ERROR: The retrieved URL will not download from microsoft's servers")

    # Applying or asking control informations once
    if not old_appx_package_name or old_appx_package_name != appx_package_name:
        # control.impacted_process and control.installed_size
        if newer_uwp_app.get("b4:Dependencies", None):
            if len(newer_uwp_app["b4:Dependencies"]) > 1:
                appx_file = sorted(
                    newer_uwp_app["b4:Dependencies"],
                    key=lambda arch: ["neutral", "x64", "x86", "arm64", "arm"].index(arch.get("Architecture")),
                )[0]["FileName"]
            else:
                appx_file = newer_uwp_app["b4:Dependencies"][0]["FileName"]
            appx_dir = appx_file.rsplit(".", 1)[0]
            unzip(newer_uwp_app["FileName"], ".", appx_file)
            unzip(appx_file)
        else:
            appx_dir = newer_uwp_app["FileName"].rsplit(".", 1)[0]
            unzip(newer_uwp_app["FileName"])
        complete_control_impacted_process(control, appx_dir)
        control.installed_size = get_size(appx_dir)
        if isdir(appx_dir):
            remove_tree(appx_dir)

        # No dependencies since it will be contained
        control.depends = ""
        control.save_control_to_wapt()

        # control.architecture
        control.architecture = get_uwp_architectures(newer_uwp_app)
        if "," in control.architecture:
            complete_control_min_wapt_version(control, "2.4", True)

        # control.min_os_version and control.max_os_version
        set_control_os_version_uwp_app(newer_uwp_app)

        # control.name
        control_name = bs_find(microsoft_store_url + "?gl=US&hl=en-US", "meta", "property", "og:title", allow_redirects=True, proxies=proxies)
        if control_name:
            control_name = control_name["content"]
        else:
            control_name = control.name
        control_name = control_name.split(" - Official app in the Microsoft Store")[0].split(" - Microsoft Apps")[0]
        control_name = complete_control_name(control, control_name)

        # control.package
        control_package = package_prefix + "-" + control_name.lower()
        complete_control_package(control, control_package, params.get("running_as_luti"))

        # control.description
        control_description = bs_find(
            microsoft_store_url + "?gl=US&hl=en-US", "meta", "property", "og:description", allow_redirects=True, proxies=proxies
        )
        if control_description:
            control_description = control_description["content"]
        else:
            control_description = control.description

        complete_control_description(control, control_description, params.get("running_as_luti"), "update_package", 250)

        # control.description_fr = bs_find(microsoft_store_url + "?gl=FR&hl=fr-FR", "meta", "property", "og:description", allow_redirects=True, proxies=proxies)["content"]

        # control.categories
        complete_control_categories(control)

    # Updating setup.py appx_package_name variable
    new_lines = []
    with open("setup.py", "r", encoding="utf8") as f:
        for line in f.readlines():
            if line.startswith("appx_package_name"):
                line = 'appx_package_name = "%s"\n' % appx_package_name
            new_lines.append(line)
    with open("setup.py", "w", encoding="utf8", newline="\n") as f:
        f.writelines(new_lines)

    # Get icon.png
    icon_png = []
    if "b4:Dependencies" in newer_uwp_app:
        if newer_uwp_app["b4:Dependencies"]:
            temp_appx = unzip(newer_uwp_app["FileName"], ".", newer_uwp_app["b4:Dependencies"][0]["FileName"], False)
            icon_png = unzip(newer_uwp_app["b4:Dependencies"][0]["FileName"], ".", "*.targetsize-48_altform-unplated.png", False)
            if not icon_png:
                icon_png = unzip(newer_uwp_app["b4:Dependencies"][0]["FileName"], ".", "*.targetsize-48.png", False)
            if not icon_png:
                icon_png = unzip(newer_uwp_app["b4:Dependencies"][0]["FileName"], ".", "**/PkgSmallLogo.png", False)
            if icon_png:
                shutil.move(icon_png[0], "WAPT\\icon.png")
            for f in temp_appx:
                if isfile(f):
                    remove_file(f)
    if not icon_png:
        icon_png = unzip(newer_uwp_app["FileName"], ".", "*.targetsize-48_altform-unplated.png", False)
        if not icon_png:
            icon_png = unzip(newer_uwp_app["FileName"], ".", "*.targetsize-48.png", False)
        if icon_png:
            shutil.move(icon_png[0], "WAPT\\icon.png")
    [remove_file(a) for a in glob.glob("*.png")]

    # Placing binaries in a dir ["appxbundle", "msixbundle", "appx", "msix]
    for f in glob.glob("*.part"):
        remove_file(f)
    bins_dir = control.package.split("-", 1)[1]
    if isdir(bins_dir):
        remove_tree(bins_dir)
    mkdirs(bins_dir)
    for uwp_file in glob.glob(f'{newer_uwp_app["Name"]}*{newer_uwp_app["Version"]}*.*'):
        if not isfile(makepath(bins_dir, uwp_file)):
            shutil.move(uwp_file, bins_dir)
    if uwp_app_dict[newer_uwp_app["FileName"]]["Dependencies"] is not None:
        for l in [glob.glob(a["Name"] + "_*") for a in uwp_app_dict[newer_uwp_app["FileName"]]["Dependencies"]]:
            for f in l:
                if not isfile(makepath(bins_dir, f)):
                    shutil.move(f, bins_dir)

    # Removing remaining files ["appxbundle", "msixbundle", "appx", "msix]
    for f in glob.glob("*.appxbundle") + glob.glob("*.msixbundle") + glob.glob("*.appx") + glob.glob("*.msix"):
        remove_file(f)

    # Changing version of the package and validating update-package-sources
    return complete_control_version(control, version)


def json_write_file(json_file, data, indent=4, sort_keys=False, encoding="utf-8", newline="\n"):
    """
    Write dictionary to a JSON file.

    Args:
        json_file (str): Path to the JSON file.
        data (dict): Dictionary content.
        indent (int or str): Tabulation size for indentation; default: 4 spaces.
        sort_keys (bool): Sort the keys alphabetically or not; default: False.
        encoding (str): File encoding; default: 'utf-8'.
        newline (str): Newline character(s) to use; default: 'LF'.
    """
    with open(json_file, "w", encoding=encoding, newline=newline) as write_file:
        json.dump(data, write_file, sort_keys=sort_keys, indent=indent)


def download_app_files(all_files, appx_package_name, proxies=None, ignored_versions=[], version_prefix=None):
    for app_file in all_files:
        latest_bin = app_file["bin_name"]
        if not latest_bin.startswith(f"{appx_package_name}_"):  # ignore other files
            continue
        if latest_bin.split(".")[-1].lower().startswith("e"):  # ignore encrypted UWP apps
            continue
        if version_prefix is not None and not Version(app_file["version"], len(version_prefix.split("."))) == Version(
            version_prefix, len(version_prefix.split("."))
        ):
            continue
        if any(
            Version(app_file["version"], len(ignored_version.split("."))) == Version(ignored_version, len(ignored_version.split(".")))
            for ignored_version in ignored_versions
        ):
            continue
        download_url = app_file["download_url"]
        if download_url.split("/")[2].endswith("microsoft.com"):
            if not isfile(latest_bin):
                print("Downloading: %s" % latest_bin)
                wget(download_url, latest_bin, proxies=proxies)
            else:
                print("Binary is present: %s" % latest_bin)
        else:
            error("ERROR: The retrieved URL will not download from Microsoft's servers")


def get_uwp_architectures(newer_uwp_app):
    """
    Returns a comma-separated string of compatible architectures extracted from the 'control.architecture'
    within the provided 'newer_uwp_app' dictionary.

    Args:
        newer_uwp_app (dict): A dictionary representing a Universal Windows Platform (UWP) app.

    Returns:
        str: A comma-separated string of compatible architectures (e.g., "x64,arm64,x86,arm"). If no
        compatible architectures are found, it returns "all".
    """
    architecture_list = []

    if newer_uwp_app.get("b4:Dependencies", None):
        for before_dependency in newer_uwp_app.get("b4:Dependencies"):
            architecture_list.append(before_dependency["Architecture"])
        sorted_architecture_list = sorted(architecture_list, key=lambda arch: ["neutral", "x64", "x86", "arm64", "arm"].index(arch))
        control_architecture = ",".join(sorted_architecture_list)

        if control_architecture.startswith("x64,x86") or "neutral" in control_architecture:
            control_architecture = "all"

        return control_architecture
    else:
        return get_uwp_filename_arch(newer_uwp_app["FileName"], newer_uwp_app["Name"])


def get_uwp_filename_arch(appx_filename, appx_package_name=None):
    """
    Returns the architecture of a Universal Windows Platform (UWP) app based on the provided 'appx_filename'
    and optionally, the 'appx_package_name'.

    Args:
        appx_filename (str): The filename of the UWP app package.
        appx_package_name (str, optional): The package name of the UWP app. Defaults to None.

    Returns:
        str: The architecture of the UWP app, which can be "x64", "arm64", "x86", or "all" (if no specific
        architecture is detected).
    """
    if not appx_package_name:
        appx_package_name = None
    if len(glob.glob(f'{appx_package_name}*{appx_filename.split("_")[1]}*')) > 1:
        pass
    elif "arm64" in appx_filename:
        return "arm64"
    elif "arm" in appx_filename:
        return "arm"
    elif "x64" in appx_filename:
        return "x64"
    if appx_filename is not None and "x86" in appx_filename and (appx_package_name is None or not appx_package_name in appx_filename):
        return "x86"

    return "all"


def get_newer_uwp_app(uwp_app_dict, version_prefix=None, min_version=None, max_version=None, tdf_list=["Windows.Universal", "Windows.Desktop"]):
    """Get the newer Universal Windows Platform (UWP) app from a dictionary of UWP apps based on specified criteria.

    Args:
        uwp_app_dict (dict): A dictionary containing UWP app information with app IDs as keys and app details as values.
        version_prefix (str, optional): The prefix of the version number to filter the apps. Defaults to None.
        min_version (str, optional): The minimum version of the UWP app. Defaults to None.
        max_version (str, optional): The maximum version of the UWP app. Defaults to None.
        tdf_list (list, optional): A list of target device families to filter the apps. Defaults to ["Windows.Universal", "Windows.Desktop"].

    Returns:
        dict or None: The dictionary containing the details of the newer UWP app that matches the specified criteria, or None if no app is found.

    """
    newer_version = "0"

    for uwp_app in uwp_app_dict.values():
        to_skip = True
        if version_prefix is not None and Version(uwp_app["Version"], len(version_prefix.split("."))) != Version(
            version_prefix, len(version_prefix.split("."))
        ):
            continue
        if tdf_list is not None and uwp_app["TargetDeviceFamily"] is not None:
            if not uwp_app["TargetDeviceFamily"]:
                continue
            for tdf in tdf_list:
                for uwp_app_tdf in uwp_app["TargetDeviceFamily"]:
                    if (
                        tdf == uwp_app_tdf["Name"]
                        and (min_version is None or Version(min_version, 3) == Version(uwp_app_tdf["MinVersion"], 3))
                        and (max_version is None or Version(max_version, 3) == Version(uwp_app_tdf["MaxVersionTested"], 3))
                    ):
                        to_skip = False
        else:
            to_skip = False

        if to_skip:
            continue

        if control.max_os_version:
            if not Version(uwp_app["MinVersion"], 3) < Version(control.max_os_version, 3):
                continue
        if Version(newer_version) < Version(uwp_app["Version"]):
            newer_uwp_app = uwp_app
            newer_version = newer_uwp_app["Version"]
    return newer_uwp_app


def get_newer_uwp_depency(dependency_dict, all_files_dict, version_prefix=None, min_version=None):
    """Returns a list of the bin_name of the latest required dependencies"""
    newer_version = "0"

    for uwp_app in all_files_dict:
        if not uwp_app["bin_name"].startswith(f'{dependency_dict["Name"]}_'):
            continue
        if version_prefix is not None and Version(uwp_app["version"], len(version_prefix.split("."))) != Version(
            version_prefix, len(version_prefix.split("."))
        ):
            continue

        if Version(newer_version) < Version(uwp_app["version"]):
            newer_uwp_depency = uwp_app
            newer_version = uwp_app["version"]

    return newer_uwp_depency["bin_name"].split(newer_version + "_")[0] + newer_version + "_"


def make_uwp_app_dict(appx_package_name):
    import xmltodict

    ms_app_db = {}
    # for ms_app_file in (
    #     glob.glob("*.appxbundle")
    #     + glob.glob("*.msixbundle")
    #     + glob.glob("*.appx")
    #     + glob.glob("*.msix")
    # ):
    for ms_app_file in (
        glob.glob(f"{appx_package_name}*.appxbundle")
        + glob.glob(f"{appx_package_name}*.msixbundle")
        + glob.glob(f"{appx_package_name}*.appx")
        + glob.glob(f"{appx_package_name}*.msix")
    ):
        data_dict = {}
        before_dependencies = []
        sub_dependencies = []
        dependency_data_dict = None

        manifest = unzip(ms_app_file, ".", "AppxManifest.xml", False)
        bundle_manifest = unzip(ms_app_file, ".", "AppxMetadata\\AppxBundleManifest.xml", False)
        ms_app_info = {
            "FileName": ms_app_file,
        }

        if not manifest:
            if bundle_manifest:
                with open(bundle_manifest[0], encoding="utf8") as xml_file:
                    data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

                if type(data_dict["Bundle"]["Packages"]["Package"]) == dict:
                    data_dict["Bundle"]["Packages"]["Package"] = [dict(data_dict["Bundle"]["Packages"]["Package"])]

                for app_pkg in list(data_dict["Bundle"]["Packages"]["Package"]):
                    if app_pkg["Type"] == "application":
                        before_dependency_info = {
                            "FileName": app_pkg["FileName"],
                            "Version": app_pkg["Version"],
                            "Architecture": app_pkg["Architecture"],
                        }
                        before_dependencies.append(before_dependency_info)

                if before_dependencies:
                    for dependency in before_dependencies:
                        unzip(
                            ms_app_file,
                            ".",
                            makepath(
                                dependency["FileName"],
                            ),
                            False,
                        )
                        manifest = unzip(dependency["FileName"], ".", makepath("AppxManifest.xml"), False)
                        if isfile(dependency["FileName"]):
                            remove_file(dependency["FileName"])
                        with open(manifest[0], encoding="utf8") as xml_file:
                            dependency_data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

                    if dependency_data_dict["Package"].get("Dependencies"):
                        if dependency_data_dict["Package"]["Dependencies"].get("PackageDependency"):
                            sub_dependencies = list(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])
                            if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == dict:
                                sub_dependencies = [dict(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])]
                            if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == list:
                                sub_dependencies = dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]
                        if dependency_data_dict["Package"]["Dependencies"].get("TargetDeviceFamily"):
                            if not "TargetDeviceFamily" in ms_app_info:
                                if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == dict:
                                    ms_app_info["TargetDeviceFamily"] = [dict(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"])]
                                if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == list:
                                    ms_app_info["TargetDeviceFamily"] = dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]
            else:
                error("nothing to parse")
        else:
            manifest = unzip(ms_app_file, ".", makepath("AppxManifest.xml"), False)
            with open(manifest[0], encoding="utf8") as xml_file:
                dependency_data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

        if dependency_data_dict["Package"].get("Dependencies"):
            if "PackageDependency" in dependency_data_dict["Package"]["Dependencies"]:
                sub_dependencies = list(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])
                if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == dict:
                    sub_dependencies = [dict(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])]
                if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == list:
                    sub_dependencies = dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]
            if "TargetDeviceFamily" in dependency_data_dict["Package"]["Dependencies"]:
                if not "TargetDeviceFamily" in ms_app_info:
                    if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == dict:
                        ms_app_info["TargetDeviceFamily"] = [dict(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"])]
                    if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == list:
                        ms_app_info["TargetDeviceFamily"] = dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]
        else:
            ms_app_info.update({"Dependencies": None})

        if ms_app_info.get("TargetDeviceFamily"):
            ms_app_info.update(
                {
                    "MinVersion": ms_app_info["TargetDeviceFamily"][0]["MinVersion"],
                    "MaxVersionTested": ms_app_info["TargetDeviceFamily"][0]["MaxVersionTested"],
                }
            )
        elif dependency_data_dict is not None and dependency_data_dict["Package"].get("Prerequisites"):
            ms_app_info.update(
                {
                    "MinVersion": dependency_data_dict["Package"]["Prerequisites"]["OSMinVersion"],
                    "MaxVersionTested": dependency_data_dict["Package"]["Prerequisites"]["OSMaxVersionTested"],
                }
            )
        else:
            ms_app_info.update({"TargetDeviceFamily": None})

        if data_dict:
            ms_app_info.update(data_dict["Bundle"]["Identity"])
        else:
            ms_app_info.update(dependency_data_dict["Package"]["Identity"])
        if "ProcessorArchitecture" in ms_app_info:
            ms_app_info.update({"Architecture": ms_app_info["ProcessorArchitecture"]})
        if before_dependencies:
            ms_app_info["b4:Dependencies"] = before_dependencies
        else:
            ms_app_info.update({"b4:Dependencies": None})

        if sub_dependencies:
            ms_app_info["Dependencies"] = sub_dependencies
        else:
            ms_app_info.update({"Dependencies": None})

        ms_app_db[ms_app_file] = ms_app_info

        for xml_file in glob.glob("AppxManifest.xml") + glob.glob("AppxBundleManifest.xml"):
            remove_file(xml_file)

    return ms_app_db


def set_control_os_version_uwp_app(
    newer_uwp_app,
    force_values=False,
    priority_windows=WindowsVersions.Windows11,
    eol_windows=WindowsVersions.Windows10v2004,
    silent=False,
):
    if newer_uwp_app.get("MinVersion") and newer_uwp_app.get("MaxVersionTested"):
        control.min_os_version = ".".join(
            newer_uwp_app["MinVersion"].split(".")[: 2 if ".".join(newer_uwp_app["MinVersion"].split(".")[:3]).endswith("0") else 3]
        )
        # MaxVersionTested value seems not reliable, now asking to change control.max_os_version
        if not Version(newer_uwp_app["MaxVersionTested"], 3) <= eol_windows:  # Ignore end-of-life Windows versions
            if control.max_os_version != ".".join(newer_uwp_app["MaxVersionTested"].split(".")[:3]):
                if force_values:
                    control.max_os_version = ".".join(newer_uwp_app["MaxVersionTested"].split(".")[:3])
                else:
                    if not silent:
                        control_max_os_version = ask_input(
                            control.package,
                            f'INFO: You may wanna change "control.max_os_version" by "{".".join(newer_uwp_app["MaxVersionTested"].split(".")[:3])}" or "{newer_uwp_app["MaxVersionTested"]}"',
                            "",
                            raise_error=False,
                        )
                    if control_max_os_version or control_max_os_version == "":
                        control.max_os_version = control_max_os_version
                    else:
                        print(
                            f'INFO: You may wanna change "control.max_os_version" by "{".".join(newer_uwp_app["MaxVersionTested"].split(".")[:3])}"'
                        )
        else:
            if control.max_os_version != "":
                if force_values:
                    control.max_os_version = ""
                else:
                    if not silent:
                        control_max_os_version = ask_message(
                            control.package,
                            f'INFO: You may wanna erase "control.max_os_version    : {control.max_os_version}"',
                            3 + 32,
                            raise_error=False,
                        )
                    if control_max_os_version == 6:
                        control.max_os_version = ""
    control.save_control_to_wapt()

38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
3d452cd5cb9b952ffdfb6556636626afb257ea807597a6474b92395080e0f123 : WAPT/control
5cd06abee4d9bc5102f5bf44b601bf5ee747193df5321c6e1fa2f0bd4ad83699 : WAPT/icon.png
27bcc79fa6447e74f56554f84cc767a62558021ea0681b623c00a9c2c42f1ba6 : av1-video-extension/Microsoft.AV1VideoExtension_1.3.15.0_neutral_~_8wekyb3d8bbwe.appxbundle
b9d676e314b46b2ac2572202aa616d41a0165f09064617b35b837bd1dc72c9cc : luti.json
27903ed717f85f26e2825a8ad66c92ca32f76abc3c2f5a1783bbe3de430b8409 : package.json
6db466faebe97df887a4de9a6ba28831ff6c85603de155fda5f4ca943cd8a7b1 : setup.py
f31bb903630e71ceeff68ce1e3058f3b120008d9beb2d9fda7491cfe67b49662 : setupdevhelpers.py
83fbc87383e9815b844100ac6ea78893a29bea4ab585417e029710a5c4ccfeea : update_package.py
364e01205533a0c6907fb9e8a8f70353985ae81ead35b71aade9a4253184f847 : xmltodict.py