"""Logic for Image Location.""" from assets import config from assets.constants import api, asset_status as asset_status_constants, error from assets.exceptions import ( AssetFinalNotFound, AssetUploadNotFound, VendorNotFound, WrongAssetStatus, ) from assets.logic.legacy import image_location as image_location_legacy from assets.models import ( asset_final, asset_status, asset_upload, image_location as image_location_model, ows_permissions, s3_file, ) from assets.models.ows_permissions import VENDOR_RESOURCE_TYPE def get_image_location( product_id: int, image_format: str, force_uncorrected: bool = False ) -> str: """Get image location. Gets the location for an image or returns an error result if it does not exist in the s3 bucket. Args: product_id (int): Unique identifier for the product. image_format (str): Whether this is for a thumbnail or cover. force_uncorrected (bool) Whether to return non-correction images only. Returns: str: the path for the image. """ try: asset_uploads_response = asset_upload.get_asset_uploads( api_version=api.API_VERSION_V2, track_id=0, product_id=product_id, order=asset_upload.ORDER_DESC, limit=1, is_correction=(0 if force_uncorrected else None), ) asset_upload_item = asset_uploads_response[0] except AssetUploadNotFound: return image_location_legacy.get_image_location( product_id, "product", image_format ) # we strip the correction string from the image_format since v2 marks asset_uploads with # the is_correction flag and asset_final records only store the derivative type. if "_correction" in image_format and asset_upload_item["is_correction"]: image_format = image_format.replace("_correction", "") try: asset_final_item = asset_final.get_asset_final_by_asset_upload_id_and_subtype( asset_upload_item["id"], image_format ) except AssetFinalNotFound as e: # we have a v2 asset upload but no asset final. # check asset_status asset_status_item = asset_status.get_last_asset_status(asset_upload_item["id"]) if ( asset_status_item["status"] in asset_status_constants.PROCESSING_FAILED_ASSET_STATUSES ): error_message = error.ERROR_ASSET_WRONG_STATUS.format( status=asset_status_item["status"] ) else: error_message = asset_status_constants.ASSET_ENCODING_IN_PROGRESS.format( status=asset_status_item["status"] ) raise WrongAssetStatus(error_message) from e # generate URL for v2 cover file_path = asset_final_item["filename"] filename = file_path.replace("images/", "") s3_check_result = s3_file.check_s3_file_exists( config.ASSET_STORAGE_BUCKET_NAME, file_path ) if not s3_check_result: return image_location_legacy.get_image_location( product_id, "product", image_format ) return image_location_model.get_image_location_by_filename( filename=filename, cdn=config.CDN_URL ) def get_profile_image(profile_id: int, profile_type: str) -> str: """Return profile image for profile id and profile type.""" permissions_response = ows_permissions.get_label_resources(profile_type, profile_id) # Pull the first reference to a vendor resource from result vendor_id = ( next( ( item for item in permissions_response["items"] if (item["type"] == VENDOR_RESOURCE_TYPE) ), {"id": None}, ) )["id"] if not vendor_id: raise VendorNotFound(error.ERROR_VENDOR_NOT_FOUND) return image_location_legacy.get_image_location(vendor_id, "vendor", "logo") def validate_product_artwork(product_id: int) -> None: """Check completeness of product artwork. Args: product_id (int): ID of the product to check for artwork. """ asset_uploads_response = asset_upload.get_asset_uploads( api_version=api.API_VERSION_V2, track_id=0, product_id=product_id, order=asset_upload.ORDER_DESC, limit=1, ) last_upload = asset_uploads_response[0] asset_status_response = asset_status.get_last_asset_status( asset_upload_id=last_upload["id"] ) status = asset_status_response.get("status") if status != asset_status_constants.STATUS_ENCODING_COMPLETED: raise WrongAssetStatus(error.ERROR_ASSET_WRONG_STATUS.format(status=status)) def get_image_locations( ids: list[int], image_format: str, fallback: bool = True, omit_corrections: bool = False, ) -> dict[int, str]: """Bulk image location logic layer, wraps model's output in a response. Args: ids (list[int]): List of of product_ids. image_format (str): the cover type: cover, large_cover, xlarge_cover. fallback (bool): to use fallback data from legacy for missing images in v2 omit_corrections (bool): to omit corrections from image locations: Returns: dict: dictionary of product_id to artwork URL. """ return image_location_model.get_image_locations( ids, image_format, fallback, omit_corrections )